1 // run 2 3 // Copyright 2014 The Go Authors. All rights reserved. 4 // 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 22 package main 23 24 import "runtime" 25 26 var c bool 27 28 func f() interface{} { 29 if c { // disable inlining 30 f() 31 } 32 runtime.GC() 33 return nil 34 } 35 36 func g() { 37 if c { // disable inlining 38 g() 39 } 40 var s interface{} 41 _ = func() { 42 s := f() 43 _ = s 44 } 45 s = f() 46 useiface(s) 47 useiface(s) 48 } 49 50 func useiface(x interface{}) { 51 if c { // disable inlining 52 useiface(x) 53 } 54 } 55 56 func h() { 57 if c { // disable inlining 58 h() 59 } 60 var x [16]uintptr 61 for i := range x { 62 x[i] = 1 63 } 64 65 useint(x[0]) 66 useint(x[1]) 67 useint(x[2]) 68 useint(x[3]) 69 } 70 71 func useint(x uintptr) { 72 if c { // disable inlining 73 useint(x) 74 } 75 } 76 77 func main() { 78 // scribble non-zero values on stack 79 h() 80 // call function that used to let the garbage collector 81 // see uninitialized stack values; it will see the 82 // nonzero values. 83 g() 84 } 85 86 func big(x int) { 87 if x >= 0 { 88 big(x-1) 89 } 90 } 91