summaryrefslogtreecommitdiff
path: root/test/fixedbugs/bug484.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/fixedbugs/bug484.go')
-rw-r--r--test/fixedbugs/bug484.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/test/fixedbugs/bug484.go b/test/fixedbugs/bug484.go
new file mode 100644
index 000000000..c664b83af
--- /dev/null
+++ b/test/fixedbugs/bug484.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.
+
+// The liveness code used to say that, in func g, s was live
+// starting at its declaration, because it appears to have its
+// address taken by the closure (different s, but the parser
+// gets slightly confused, a separate bug). The liveness analysis
+// saw s as having its address taken but the register optimizer
+// did not. This mismatch meant that s would be marked live
+// (and therefore initialized) at the call to f, but the register optimizer
+// would optimize away the initialization of s before f, causing the
+// garbage collector to use unused data.
+// The register optimizer has been changed to respect the
+// same "address taken" flag that the liveness analysis uses,
+// even if it cannot see any address being taken in the actual
+// machine code. This is conservative but keeps the two consistent,
+// which is the most important thing.
+
+package main
+
+import "runtime"
+
+var c bool
+
+func f() interface{} {
+ if c { // disable inlining
+ f()
+ }
+ runtime.GC()
+ return nil
+}
+
+func g() {
+ if c { // disable inlining
+ g()
+ }
+ var s interface{}
+ _ = func() {
+ s := f()
+ _ = s
+ }
+ s = f()
+ useiface(s)
+ useiface(s)
+}
+
+func useiface(x interface{}) {
+ if c { // disable inlining
+ useiface(x)
+ }
+}
+
+func h() {
+ if c { // disable inlining
+ h()
+ }
+ var x [16]uintptr
+ for i := range x {
+ x[i] = 1
+ }
+
+ useint(x[0])
+ useint(x[1])
+ useint(x[2])
+ useint(x[3])
+}
+
+func useint(x uintptr) {
+ if c { // disable inlining
+ useint(x)
+ }
+}
+
+func main() {
+ // scribble non-zero values on stack
+ h()
+ // call function that used to let the garbage collector
+ // see uninitialized stack values; it will see the
+ // nonzero values.
+ g()
+}
+
+func big(x int) {
+ if x >= 0 {
+ big(x-1)
+ }
+}