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 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