|  | // 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" | 
|  |  | 
|  | //go:noinline | 
|  | func f() interface{} { | 
|  | runtime.GC() | 
|  | return nil | 
|  | } | 
|  |  | 
|  | //go:noinline | 
|  | func g() { | 
|  | var s interface{} | 
|  | _ = func() { | 
|  | s := f() | 
|  | _ = s | 
|  | } | 
|  | s = f() | 
|  | useiface(s) | 
|  | useiface(s) | 
|  | } | 
|  |  | 
|  | //go:noinline | 
|  | func useiface(x interface{}) { | 
|  | } | 
|  |  | 
|  | //go:noinline | 
|  | func h() { | 
|  | var x [16]uintptr | 
|  | for i := range x { | 
|  | x[i] = 1 | 
|  | } | 
|  |  | 
|  | useint(x[0]) | 
|  | useint(x[1]) | 
|  | useint(x[2]) | 
|  | useint(x[3]) | 
|  | } | 
|  |  | 
|  | //go:noinline | 
|  | func useint(x uintptr) { | 
|  | } | 
|  |  | 
|  | 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) | 
|  | } | 
|  | } |