github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/test/fixedbugs/bug484.go (about)

     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  }