Home | History | Annotate | Download | only in fixedbugs
      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 //go:noinline
     27 func f() interface{} {
     28 	runtime.GC()
     29 	return nil
     30 }
     31 
     32 //go:noinline
     33 func g() {
     34 	var s interface{}
     35 	_ = func() {
     36 		s := f()
     37 		_ = s
     38 	}
     39 	s = f()
     40 	useiface(s)
     41 	useiface(s)
     42 }
     43 
     44 //go:noinline
     45 func useiface(x interface{}) {
     46 }
     47 
     48 //go:noinline
     49 func h() {
     50 	var x [16]uintptr
     51 	for i := range x {
     52 		x[i] = 1
     53 	}
     54 
     55 	useint(x[0])
     56 	useint(x[1])
     57 	useint(x[2])
     58 	useint(x[3])
     59 }
     60 
     61 //go:noinline
     62 func useint(x uintptr) {
     63 }
     64 
     65 func 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 
     74 func big(x int) {
     75 	if x >= 0 {
     76 		big(x - 1)
     77 	}
     78 }
     79