From 30f0d5c388b623a4d6052f28c221b57ba988aa29 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 6 Aug 2014 17:02:55 -0400 Subject: test/mapnan.go: add regression test for non-empty interfaces. LGTM=rsc, khr R=rsc, khr, bradfitz CC=golang-codereviews https://codereview.appspot.com/126720043 --- test/map.go | 2 +- test/maplinear.go | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/mapnan.go | 56 --------------------- 3 files changed, 144 insertions(+), 57 deletions(-) create mode 100644 test/maplinear.go delete mode 100644 test/mapnan.go (limited to 'test') diff --git a/test/map.go b/test/map.go index 485e743fe..2c1cf8a14 100644 --- a/test/map.go +++ b/test/map.go @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file. // Test maps, almost exhaustively. -// NaN complexity test is in mapnan.go. +// Complexity (linearity) test is in maplinear.go. package main diff --git a/test/maplinear.go b/test/maplinear.go new file mode 100644 index 000000000..56e50951a --- /dev/null +++ b/test/maplinear.go @@ -0,0 +1,143 @@ +// +build darwin linux +// run + +// Copyright 2013 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 that maps don't go quadratic for NaNs and other values. + +package main + +import ( + "fmt" + "math" + "time" +) + +// checkLinear asserts that the running time of f(n) is in O(n). +// tries is the initial number of iterations. +func checkLinear(typ string, tries int, f func(n int)) { + // Depending on the machine and OS, this test might be too fast + // to measure with accurate enough granularity. On failure, + // make it run longer, hoping that the timing granularity + // is eventually sufficient. + + timeF := func(n int) time.Duration { + t1 := time.Now() + f(n) + return time.Since(t1) + } + + t0 := time.Now() + + n := tries + fails := 0 + for { + t1 := timeF(n) + t2 := timeF(2 * n) + + // should be 2x (linear); allow up to 3x + if t2 < 3*t1 { + if false { + fmt.Println(typ, "\t", time.Since(t0)) + } + return + } + fails++ + if fails == 6 { + panic(fmt.Sprintf("%s: too slow: %d inserts: %v; %d inserts: %v\n", + typ, n, t1, 2*n, t2)) + } + if fails < 4 { + n *= 2 + } + } +} + +type I interface { + f() +} + +type C int + +func (C) f() {} + +func main() { + // NaNs. ~31ms on a 1.6GHz Zeon. + checkLinear("NaN", 30000, func(n int) { + m := map[float64]int{} + nan := math.NaN() + for i := 0; i < n; i++ { + m[nan] = 1 + } + if len(m) != n { + panic("wrong size map after nan insertion") + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("eface", 10000, func(n int) { + m := map[interface{}]int{} + for i := 0; i < n; i++ { + m[i] = 1 + } + }) + + // ~7ms on a 1.6GHz Zeon. + // Regression test for CL 119360043. + checkLinear("iface", 10000, func(n int) { + m := map[I]int{} + for i := 0; i < n; i++ { + m[C(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("int", 10000, func(n int) { + m := map[int]int{} + for i := 0; i < n; i++ { + m[i] = 1 + } + }) + + // ~18ms on a 1.6GHz Zeon. + checkLinear("string", 10000, func(n int) { + m := map[string]int{} + for i := 0; i < n; i++ { + m[fmt.Sprint(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("float32", 10000, func(n int) { + m := map[float32]int{} + for i := 0; i < n; i++ { + m[float32(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("float64", 10000, func(n int) { + m := map[float64]int{} + for i := 0; i < n; i++ { + m[float64(i)] = 1 + } + }) + + // ~22ms on a 1.6GHz Zeon. + checkLinear("complex64", 10000, func(n int) { + m := map[complex64]int{} + for i := 0; i < n; i++ { + m[complex(float32(i), float32(i))] = 1 + } + }) + + // ~32ms on a 1.6GHz Zeon. + checkLinear("complex128", 10000, func(n int) { + m := map[complex128]int{} + for i := 0; i < n; i++ { + m[complex(float64(i), float64(i))] = 1 + } + }) +} diff --git a/test/mapnan.go b/test/mapnan.go deleted file mode 100644 index f081cab01..000000000 --- a/test/mapnan.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build darwin linux -// run - -// Copyright 2013 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 that NaNs in maps don't go quadratic. - -package main - -import ( - "fmt" - "math" - "time" -) - -func main() { - - // Test that NaNs in maps don't go quadratic. - t := func(n int) time.Duration { - t1 := time.Now() - m := map[float64]int{} - nan := math.NaN() - for i := 0; i < n; i++ { - m[nan] = 1 - } - if len(m) != n { - panic("wrong size map after nan insertion") - } - return time.Since(t1) - } - - // Depending on the machine and OS, this test might be too fast - // to measure with accurate enough granularity. On failure, - // make it run longer, hoping that the timing granularity - // is eventually sufficient. - - n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7) - fails := 0 - for { - t1 := t(n) - t2 := t(2 * n) - // should be 2x (linear); allow up to 3x - if t2 < 3*t1 { - return - } - fails++ - if fails == 6 { - panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2)) - } - if fails < 4 { - n *= 2 - } - } -} -- cgit v1.2.1 From 3852374b292ff97096b0dcd6a6e2955ede1527fb Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 8 Aug 2014 10:43:44 -0700 Subject: test: add another test case that gccgo crashed on LGTM=bradfitz R=golang-codereviews, bradfitz CC=golang-codereviews https://codereview.appspot.com/124020044 --- test/fixedbugs/bug490.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/fixedbugs/bug490.go (limited to 'test') diff --git a/test/fixedbugs/bug490.go b/test/fixedbugs/bug490.go new file mode 100644 index 000000000..7d05f3945 --- /dev/null +++ b/test/fixedbugs/bug490.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2014 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. + +// The gccgo compiler used to crash building a comparison between an +// interface and an empty struct literal. + +package p + +type S struct{} + +func F(v interface{}) bool { + return v == S{} +} -- cgit v1.2.1 From 61d32c21162e7dd4e4e3dc0aeedd431d7ee95af4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 11 Aug 2014 15:24:36 -0400 Subject: cmd/6g, cmd/8g: fix, test byte-sized magic multiply Credit to R?my for finding and writing test case. Fixes issue 8325. LGTM=r R=golang-codereviews, r CC=dave, golang-codereviews, iant, remyoudompheng https://codereview.appspot.com/124950043 --- test/fixedbugs/issue8325.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/fixedbugs/issue8325.go (limited to 'test') diff --git a/test/fixedbugs/issue8325.go b/test/fixedbugs/issue8325.go new file mode 100644 index 000000000..e22fd319d --- /dev/null +++ b/test/fixedbugs/issue8325.go @@ -0,0 +1,31 @@ +// run + +// Copyright 2014 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 8325: corrupted byte operations during optimization +// pass. + +package main + +const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +func main() { + var bytes = []byte{10, 20, 30, 40, 50} + + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + + for _, b := range bytes { + switch { + case '0' <= b && b <= '9', + 'A' <= b && b <= 'Z': + default: + println("found a bad character", string(b)) + panic("BUG") + } + + } +} -- cgit v1.2.1 From 3b851200349bccc6484291cd7af5f7d8b464c84d Mon Sep 17 00:00:00 2001 From: Chris Manghane Date: Mon, 11 Aug 2014 16:11:55 -0700 Subject: cmd/gc: comma-ok assignments produce untyped bool as 2nd result LGTM=rsc R=gri, rsc CC=golang-codereviews https://codereview.appspot.com/127950043 --- test/fixedbugs/issue8475.go | 25 +++++++++++++++++++++++++ test/named1.go | 8 ++++---- 2 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 test/fixedbugs/issue8475.go (limited to 'test') diff --git a/test/fixedbugs/issue8475.go b/test/fixedbugs/issue8475.go new file mode 100644 index 000000000..e69794534 --- /dev/null +++ b/test/fixedbugs/issue8475.go @@ -0,0 +1,25 @@ +// build + +// Copyright 2014 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 8745: comma-ok assignments should produce untyped bool as 2nd result. + +package main + +type mybool bool + +func main() { + var ok mybool + _ = ok + + var i interface{} + _, ok = i.(int) + + var m map[int]int + _, ok = m[0] + + var c chan int + _, ok = <-c +} diff --git a/test/named1.go b/test/named1.go index 62b874c5c..febad64ec 100644 --- a/test/named1.go +++ b/test/named1.go @@ -41,21 +41,21 @@ func main() { asBool(1 != 2) // ok now asBool(i < j) // ok now - _, b = m[2] // ERROR "cannot .* bool.*type Bool" + _, b = m[2] // ok now var inter interface{} - _, b = inter.(Map) // ERROR "cannot .* bool.*type Bool" + _, b = inter.(Map) // ok now _ = b var minter interface { M() } - _, b = minter.(Map) // ERROR "cannot .* bool.*type Bool" + _, b = minter.(Map) // ok now _ = b _, bb := <-c asBool(bb) // ERROR "cannot use.*type bool.*as type Bool" - _, b = <-c // ERROR "cannot .* bool.*type Bool" + _, b = <-c // ok now _ = b asString(String(slice)) // ok -- cgit v1.2.1 From 1849dc0f1fe5915df8506c99b4f6f801defcc0ef Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 15 Aug 2014 11:33:31 -0700 Subject: cmd/gc: disallow pointer constants Fixes issue 7760. LGTM=iant R=iant, remyoudompheng CC=golang-codereviews https://codereview.appspot.com/130720043 Committer: Ian Lance Taylor --- test/fixedbugs/issue7760.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/fixedbugs/issue7760.go (limited to 'test') diff --git a/test/fixedbugs/issue7760.go b/test/fixedbugs/issue7760.go new file mode 100644 index 000000000..cccae4891 --- /dev/null +++ b/test/fixedbugs/issue7760.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2014 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. + +// Verify that pointers can't be used as constants. + +package main + +import "unsafe" + +type myPointer unsafe.Pointer + +const _ = unsafe.Pointer(uintptr(1)) // ERROR "is not (a )?constant" +const _ = myPointer(uintptr(1)) // ERROR "is not (a )?constant" + +const _ = (*int)(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant" +const _ = (*int)(myPointer(uintptr(1))) // ERROR "is not (a )?constant" + +const _ = uintptr(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant" +const _ = uintptr(myPointer(uintptr(1))) // ERROR "is not (a )?constant" + +const _ = []byte("") // ERROR "is not (a )?constant" +const _ = []rune("") // ERROR "is not (a )?constant" -- cgit v1.2.1 From b7f5e43fbdf09081deb1ca809c6d7e822a683cd6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 18 Aug 2014 21:13:11 -0400 Subject: cmd/gc, runtime: refactor interface inlining decision into compiler We need to change the interface value representation for concurrent garbage collection, so that there is no ambiguity about whether the data word holds a pointer or scalar. This CL does NOT make any representation changes. Instead, it removes representation assumptions from various pieces of code throughout the tree. The isdirectiface function in cmd/gc/subr.c is now the only place that decides that policy. The policy propagates out from there in the reflect metadata, as a new flag in the internal kind value. A follow-up CL will change the representation by changing the isdirectiface function. If that CL causes problems, it will be easy to roll back. Update issue 8405. LGTM=iant R=golang-codereviews, iant CC=golang-codereviews, r https://codereview.appspot.com/129090043 --- test/live.go | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'test') diff --git a/test/live.go b/test/live.go index 6ac1d6a46..1c01f8dc4 100644 --- a/test/live.go +++ b/test/live.go @@ -118,7 +118,10 @@ var i9 interface{} func f9() bool { g8() x := i9 - return x != 99 + // using complex number in comparison so that + // there is always a convT2E, no matter what the + // interface rules are. + return x != 99.0i // ERROR "live at call to convT2E: x" } // liveness formerly confused by UNDEF followed by RET, @@ -184,7 +187,7 @@ func f11c() *int { func f12() *int { if b { - select{} + select {} } else { return nil } @@ -215,7 +218,7 @@ func f15() { var x string _ = &x x = g15() // ERROR "live at call to g15: x" - print(x) // ERROR "live at call to printstring: x" + print(x) // ERROR "live at call to printstring: x" } func g15() string @@ -287,7 +290,7 @@ var ch chan *byte func f19() { // dest temporary for channel receive. var z *byte - + if b { z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" } @@ -348,21 +351,21 @@ func f25(b bool) { var x string _ = &x x = g15() // ERROR "live at call to g15: x" - print(x) // ERROR "live at call to printstring: x" + print(x) // ERROR "live at call to printstring: x" } // ERROR "live at call to deferreturn: x" func g25() - + // non-escaping ... slices passed to function call should die on return, // so that the temporaries do not stack and do not cause ambiguously // live variables. func f26(b bool) { if b { - print26(1,2,3) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" } - print26(4,5,6) // ERROR "live at call to print26: autotmp_[0-9]+$" - print26(7,8,9) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" println() } @@ -374,10 +377,10 @@ func print26(...interface{}) func f27(b bool) { x := 0 if b { - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" } - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" println() } @@ -386,10 +389,10 @@ func f27(b bool) { func f27defer(b bool) { x := 0 if b { - defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" + defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" } - defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" - println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" + defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" + println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" } // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" // and newproc (go) escapes to the heap @@ -397,9 +400,9 @@ func f27defer(b bool) { func f27go(b bool) { x := 0 if b { - go call27(func() {x++}) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$" } - go call27(func() {x++}) // ERROR "live at call to newobject: &x" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x" println() } @@ -412,11 +415,11 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string func f28(b bool) { if b { - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" } - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" -} + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" +} // map iterator should die on end of range loop @@ -584,13 +587,13 @@ func f39a() (x []int) { func f39b() (x [10]*int) { x = [10]*int{new(int)} // ERROR "live at call to newobject: x" - println() // ERROR "live at call to printnl: x" + println() // ERROR "live at call to printnl: x" return x } func f39c() (x [10]*int) { x = [10]*int{new(int)} // ERROR "live at call to newobject: x" - println() // ERROR "live at call to printnl: x" + println() // ERROR "live at call to printnl: x" return } @@ -603,7 +606,7 @@ type T40 struct { func newT40() *T40 { ret := T40{ // ERROR "live at call to makemap: &ret" - make(map[int]int), + make(map[int]int), } return &ret } -- cgit v1.2.1 From 493f0289b5fa6cc2c08344c4deae2755ffe84096 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 25 Aug 2014 07:05:45 -0400 Subject: cmd/gc: fix order of channel evaluation of receive channels Normally, an expression of the form x.f or *y can be reordered with function calls and communications. Select is stricter than normal: each channel expression is evaluated in source order. If you have case <-x.f and case <-foo(), then if the evaluation of x.f causes a panic, foo must not have been called. (This is in contrast to an expression like x.f + foo().) Enforce this stricter ordering. Fixes issue 8336. LGTM=dvyukov R=golang-codereviews, dvyukov CC=golang-codereviews, r https://codereview.appspot.com/126570043 --- test/fixedbugs/issue8336.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/fixedbugs/issue8336.go (limited to 'test') diff --git a/test/fixedbugs/issue8336.go b/test/fixedbugs/issue8336.go new file mode 100644 index 000000000..26bdeabb2 --- /dev/null +++ b/test/fixedbugs/issue8336.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2014 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 8336. Order of evaluation of receive channels in select. + +package main + +type X struct { + c chan int +} + +func main() { + defer func() { + recover() + }() + var x *X + select { + case <-x.c: // should fault and panic before foo is called + case <-foo(): + } +} + +func foo() chan int { + println("BUG: foo must not be called") + return make(chan int) +} -- cgit v1.2.1 From 588ffed86c777b6270c341fffadbbfb82f2c6a9c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 25 Aug 2014 14:38:19 -0400 Subject: cmd/gc, runtime: treat slices and strings like pointers in garbage collection Before, a slice with cap=0 or a string with len=0 might have its base pointer pointing beyond the actual slice/string data into the next block. The collector had to ignore slices and strings with cap=0 in order to avoid misinterpreting the base pointer. Now, a slice with cap=0 or a string with len=0 still has a base pointer pointing into the actual slice/string data, no matter what. The collector can now always scan the pointer, which means strings and slices are no longer special. Fixes issue 8404. LGTM=khr, josharian R=josharian, khr, dvyukov CC=golang-codereviews https://codereview.appspot.com/112570044 --- test/slice3.go | 18 +++++++----- test/slicecap.go | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 test/slicecap.go (limited to 'test') diff --git a/test/slice3.go b/test/slice3.go index 3cf34b57e..857eaf3a0 100644 --- a/test/slice3.go +++ b/test/slice3.go @@ -19,10 +19,10 @@ var bout *bufio.Writer func main() { bout = bufio.NewWriter(os.Stdout) - + fmt.Fprintf(bout, "%s", programTop) fmt.Fprintf(bout, "func main() {\n") - + index := []string{ "0", "1", @@ -38,7 +38,7 @@ func main() { "v10", "v20", } - + parse := func(s string) (n int, isconst bool) { if s == "vminus1" { return -1, false @@ -69,7 +69,7 @@ func main() { iconst && kconst && iv > kv, iconst && base == "array" && iv > Cap, jconst && base == "array" && jv > Cap, - kconst && base == "array" && kv > Cap: + kconst && base == "array" && kv > Cap: continue } @@ -82,7 +82,7 @@ func main() { xlen = jv - iv xcap = kv - iv } - fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap) + fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap) } } } @@ -147,9 +147,13 @@ func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) { println(desc, "=", base, len, cap, "want panic") return } - if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) { + if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) { notOK() - println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) + if cap == 0 { + println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap) + } else { + println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) + } } } diff --git a/test/slicecap.go b/test/slicecap.go new file mode 100644 index 000000000..dceb7e2cc --- /dev/null +++ b/test/slicecap.go @@ -0,0 +1,90 @@ +// run + +// Copyright 2014 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 "unsafe" + +var ( + hello = "hello" + bytes = []byte{1, 2, 3, 4, 5} + ints = []int32{1, 2, 3, 4, 5} + + five = 5 + + ok = true +) + +func notOK() { + if ok { + println("BUG:") + ok = false + } +} + +func checkString(desc, s string) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&hello)) + if p1-p2 >= 5 { + notOK() + println("string", desc, "has invalid base") + } +} + +func checkBytes(desc string, s []byte) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&bytes)) + if p1-p2 >= 5 { + println("byte slice", desc, "has invalid base") + } +} + +func checkInts(desc string, s []int32) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&ints)) + if p1-p2 >= 5*4 { + println("int slice", desc, "has invalid base") + } +} + +func main() { + { + x := hello + checkString("x", x) + checkString("x[5:]", x[5:]) + checkString("x[five:]", x[five:]) + checkString("x[5:five]", x[5:five]) + checkString("x[five:5]", x[five:5]) + checkString("x[five:five]", x[five:five]) + checkString("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkString("y[1:]", y[1:]) + } + { + x := bytes + checkBytes("x", x) + checkBytes("x[5:]", x[5:]) + checkBytes("x[five:]", x[five:]) + checkBytes("x[5:five]", x[5:five]) + checkBytes("x[five:5]", x[five:5]) + checkBytes("x[five:five]", x[five:five]) + checkBytes("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkBytes("y[1:]", y[1:]) + } + { + x := ints + checkInts("x", x) + checkInts("x[5:]", x[5:]) + checkInts("x[five:]", x[five:]) + checkInts("x[5:five]", x[5:five]) + checkInts("x[five:5]", x[five:5]) + checkInts("x[five:five]", x[five:five]) + checkInts("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkInts("y[1:]", y[1:]) + } +} -- cgit v1.2.1 From af750882d3738dd977ad6731cba1f5e7f6b845cf Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Aug 2014 14:08:26 -0400 Subject: runtime: give nosplit functions 32 more bytes of headroom The Go calling convention uses more stack space than C. On 64-bit systems we've been right up against the limit (128 bytes, so only 16 words) and doing awful things to our source code to work around it. Instead of continuing to do awful things, raise the limit to 160 bytes. I am prepared to raise the limit to 192 bytes if necessary, but I think this will be enough. Should fix current link-time stack overflow errors on - nacl/arm - netbsd/amd64 - openbsd/amd64 - solaris/amd64 - windows/amd64 TBR=r CC=golang-codereviews, iant https://codereview.appspot.com/131450043 --- test/nosplit.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/nosplit.go b/test/nosplit.go index 35aa51017..39bb3fcb4 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -242,7 +242,7 @@ TestCases: if line == "" { continue } - for _, subline := range strings.Split(line, ";") { + for i, subline := range strings.Split(line, ";") { subline = strings.TrimSpace(subline) if subline == "" { continue @@ -255,6 +255,14 @@ TestCases: } name := m[1] size, _ := strconv.Atoi(m[2]) + + // CL 131450043 raised the limit from 128 to 160. + // Instead of rewriting the test cases above, adjust + // the first stack frame to use up the extra 32 bytes. + if i == 0 { + size += 32 + } + if goarch == "amd64" && size%8 == 4 { continue TestCases } -- cgit v1.2.1 From 52e5ed284fb1c2425ebc12ddb79db670abb1db56 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 28 Aug 2014 19:51:21 -0700 Subject: test: add test that caused gccgo to crash on valid code Update issue 8612 LGTM=minux R=golang-codereviews, minux CC=golang-codereviews https://codereview.appspot.com/135170043 --- test/fixedbugs/issue8612.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/fixedbugs/issue8612.go (limited to 'test') diff --git a/test/fixedbugs/issue8612.go b/test/fixedbugs/issue8612.go new file mode 100644 index 000000000..93370cf66 --- /dev/null +++ b/test/fixedbugs/issue8612.go @@ -0,0 +1,34 @@ +//compile + +// Copyright 2014 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. + +// Gccgo had a bug comparing a struct or array value with an interface +// values, when the struct or array was not addressable. + +package p + +type A [10]int + +type S struct { + i int +} + +func F1() S { + return S{0} +} + +func F2() A { + return A{} +} + +func Cmp(v interface{}) bool { + if F1() == v { + return true + } + if F2() == v { + return true + } + return false +} -- cgit v1.2.1 From 8a4391297874c8421e2d489e879e3467d5340941 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 30 Aug 2014 00:56:52 -0400 Subject: runtime: increase nosplit area to 192 In CL 131450043, which raised it to 160, I'd raise it to 192 if necessary. Apparently it is necessary on windows/amd64. One note for those concerned about the growth: in the old segmented stack world, we wasted this much space at the bottom of every stack segment. In the new contiguous stack world, each goroutine has only one stack segment, so we only waste this much space once per goroutine. So even raising the limit further might still be a net savings. Fixes windows/amd64 build. TBR=r CC=golang-codereviews https://codereview.appspot.com/132480043 --- test/nosplit.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/nosplit.go b/test/nosplit.go index 39bb3fcb4..3854f2420 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -256,11 +256,11 @@ TestCases: name := m[1] size, _ := strconv.Atoi(m[2]) - // CL 131450043 raised the limit from 128 to 160. + // The limit was originally 128 but is now 192. // Instead of rewriting the test cases above, adjust // the first stack frame to use up the extra 32 bytes. if i == 0 { - size += 32 + size += 192 - 128 } if goarch == "amd64" && size%8 == 4 { -- cgit v1.2.1 From 3f94b79d4827411c92a95d8e3c76049a3784e3e0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 5 Sep 2014 10:04:16 -0400 Subject: runtime: convert panic/recover to Go created panic1.go just so diffs were available. After this CL is in, I'd like to move panic.go -> defer.go and panic1.go -> panic.go. LGTM=rsc R=rsc, khr CC=golang-codereviews https://codereview.appspot.com/133530045 Committer: Russ Cox --- test/live.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/live.go b/test/live.go index 1c01f8dc4..35099d18b 100644 --- a/test/live.go +++ b/test/live.go @@ -467,7 +467,7 @@ func f31(b1, b2, b3 bool) { h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$" } if b3 { - panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to panic: autotmp_[0-9]+$" + panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$" } print(b3) } -- cgit v1.2.1 From a67917471ff28c5e4c37ba1eca98f0a6ded14c68 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 5 Sep 2014 16:51:45 -0400 Subject: runtime: use reflect.call during panic instead of newstackcall newstackcall creates a new stack segment, and we want to be able to throw away all that code. LGTM=khr R=khr, iant CC=dvyukov, golang-codereviews, r https://codereview.appspot.com/139270043 --- test/fixedbugs/issue4388.go | 6 +++--- test/fixedbugs/issue5856.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go index 2e052e138..b18c98bac 100644 --- a/test/fixedbugs/issue4388.go +++ b/test/fixedbugs/issue4388.go @@ -17,18 +17,18 @@ type T struct { } func f1() { - // The 4 here and below depends on the number of internal runtime frames + // The 5 here and below depends on the number of internal runtime frames // that sit between a deferred function called during panic and // the original frame. If that changes, this test will start failing and // the number here will need to be updated. - defer checkLine(4) + defer checkLine(5) var t *T var c io.Closer = t c.Close() } func f2() { - defer checkLine(4) + defer checkLine(5) var t T var c io.Closer = t c.Close() diff --git a/test/fixedbugs/issue5856.go b/test/fixedbugs/issue5856.go index 35cadf8c9..78ca3b9f6 100644 --- a/test/fixedbugs/issue5856.go +++ b/test/fixedbugs/issue5856.go @@ -29,7 +29,7 @@ func f() { } func g() { - _, file, line, _ := runtime.Caller(2) + _, file, line, _ := runtime.Caller(3) if !strings.HasSuffix(file, "issue5856.go") || line != 28 { fmt.Printf("BUG: defer called from %s:%d, want issue5856.go:28\n", file, line) os.Exit(1) -- cgit v1.2.1 From 3c63238a55767eb0329761b3538362b67f66291e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 6 Sep 2014 13:19:08 -0400 Subject: runtime: fix panic/wrapper/recover math The gp->panicwrap adjustment is just fatally flawed. Now that there is a Panic.argp field, update that instead. That can be done on entry only, so that unwinding doesn't need to worry about undoing anything. The wrappers emit a few more instructions in the prologue but everything else in the system gets much simpler. It also fixes (without trying) a broken test I never checked in. Fixes issue 7491. LGTM=khr R=khr CC=dvyukov, golang-codereviews, iant, r https://codereview.appspot.com/135490044 --- test/recover.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/recover.go b/test/recover.go index 071be6667..6287d6507 100644 --- a/test/recover.go +++ b/test/recover.go @@ -47,6 +47,7 @@ func main() { test11reflect1() test11reflect2() } + test111() test12() if !interp { test12reflect1() @@ -77,7 +78,7 @@ func mustRecoverBody(v1, v2, v3, x interface{}) { } v = v2 if v == nil { - println("missing recover") + println("missing recover", x.(int)) die() // panic is useless here } if v != x { @@ -137,7 +138,7 @@ func test1WithClosures() { mustNotRecover() v := recover() if v == nil { - println("missing recover") + println("missing recover", x.(int)) die() } if v != x { @@ -406,6 +407,49 @@ func test11reflect2() { panic(11) } +// tiny receiver, so basic wrapper in i.M() +type T3deeper struct{} + +func (T3deeper) M() { + badstate() // difference from T3 + mustRecoverBody(doubleRecover(), recover(), recover(), 111) +} + +func test111() { + var i I = T3deeper{} + defer i.M() + panic(111) +} + +type Tiny struct{} + +func (Tiny) M() { + panic(112) +} + +// i.M is a wrapper, and i.M panics. +// +// This is a torture test for an old implementation of recover that +// tried to deal with wrapper functions by doing some argument +// positioning math on both entry and exit. Doing anything on exit +// is a problem because sometimes functions exit via panic instead +// of an ordinary return, so panic would have to know to do the +// same math when unwinding the stack. It gets complicated fast. +// This particular test never worked with the old scheme, because +// panic never did the right unwinding math. +// +// The new scheme adjusts Panic.argp on entry to a wrapper. +// It has no exit work, so if a wrapper is interrupted by a panic, +// there's no cleanup that panic itself must do. +// This test just works now. +func badstate() { + defer func() { + recover() + }() + var i I = Tiny{} + i.M() +} + // large receiver, so basic wrapper in i.M() type T4 [2]string -- cgit v1.2.1 From 1d2be0d3f233300d7953493b0c2f2ca315e1c7da Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 6 Sep 2014 21:16:13 -0400 Subject: runtime: increase stack split limit again Increase NOSPLIT reservation from 192 to 384 bytes. The problem is that the non-Unix systems (Solaris and Windows) just can't make system calls in a small amount of space, and then worse they do things that are complex enough to warrant calling runtime.throw on failure. We don't have time to rewrite the code to use less stack. I'm not happy about this, but it's still a small amount. The good news is that we're doing this to get to only using copying stacks for stack growth. Once that is true, we can drop the default stack size from 8k to 4k, which should more than make up for the bytes we're losing here. LGTM=r R=iant, r, bradfitz, aram.h CC=golang-codereviews https://codereview.appspot.com/140350043 --- test/nosplit.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/nosplit.go b/test/nosplit.go index 3854f2420..c9d008acd 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -256,11 +256,11 @@ TestCases: name := m[1] size, _ := strconv.Atoi(m[2]) - // The limit was originally 128 but is now 192. + // The limit was originally 128 but is now 384. // Instead of rewriting the test cases above, adjust // the first stack frame to use up the extra 32 bytes. if i == 0 { - size += 192 - 128 + size += 384 - 128 } if goarch == "amd64" && size%8 == 4 { -- cgit v1.2.1