blob: bd4fa516a235dbf5d49638f08ddb156fd42eb88c [file] [log] [blame]
Brent Austinba3052e2015-04-21 16:08:23 -07001// run
2
Dan Willemsen38f2dba2016-07-08 14:54:35 -07003// Copyright 2014 The Go Authors. All rights reserved.
Brent Austinba3052e2015-04-21 16:08:23 -07004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// The liveness code used to say that, in func g, s was live
8// starting at its declaration, because it appears to have its
9// address taken by the closure (different s, but the parser
10// gets slightly confused, a separate bug). The liveness analysis
11// saw s as having its address taken but the register optimizer
12// did not. This mismatch meant that s would be marked live
13// (and therefore initialized) at the call to f, but the register optimizer
14// would optimize away the initialization of s before f, causing the
15// garbage collector to use unused data.
16// The register optimizer has been changed to respect the
17// same "address taken" flag that the liveness analysis uses,
18// even if it cannot see any address being taken in the actual
19// machine code. This is conservative but keeps the two consistent,
20// which is the most important thing.
21
22package main
23
24import "runtime"
25
Dan Willemsen38f2dba2016-07-08 14:54:35 -070026//go:noinline
Brent Austinba3052e2015-04-21 16:08:23 -070027func f() interface{} {
Brent Austinba3052e2015-04-21 16:08:23 -070028 runtime.GC()
29 return nil
30}
31
Dan Willemsen38f2dba2016-07-08 14:54:35 -070032//go:noinline
Brent Austinba3052e2015-04-21 16:08:23 -070033func g() {
Brent Austinba3052e2015-04-21 16:08:23 -070034 var s interface{}
35 _ = func() {
36 s := f()
37 _ = s
38 }
39 s = f()
40 useiface(s)
41 useiface(s)
42}
43
Dan Willemsen38f2dba2016-07-08 14:54:35 -070044//go:noinline
Brent Austinba3052e2015-04-21 16:08:23 -070045func useiface(x interface{}) {
Brent Austinba3052e2015-04-21 16:08:23 -070046}
47
Dan Willemsen38f2dba2016-07-08 14:54:35 -070048//go:noinline
Brent Austinba3052e2015-04-21 16:08:23 -070049func h() {
Brent Austinba3052e2015-04-21 16:08:23 -070050 var x [16]uintptr
51 for i := range x {
52 x[i] = 1
53 }
Dan Willemsen38f2dba2016-07-08 14:54:35 -070054
Brent Austinba3052e2015-04-21 16:08:23 -070055 useint(x[0])
56 useint(x[1])
57 useint(x[2])
58 useint(x[3])
59}
60
Dan Willemsen38f2dba2016-07-08 14:54:35 -070061//go:noinline
Brent Austinba3052e2015-04-21 16:08:23 -070062func useint(x uintptr) {
Brent Austinba3052e2015-04-21 16:08:23 -070063}
64
65func main() {
66 // scribble non-zero values on stack
67 h()
68 // call function that used to let the garbage collector
69 // see uninitialized stack values; it will see the
70 // nonzero values.
71 g()
72}
73
74func big(x int) {
75 if x >= 0 {
Dan Willemsen38f2dba2016-07-08 14:54:35 -070076 big(x - 1)
Brent Austinba3052e2015-04-21 16:08:23 -070077 }
78}