...
Run Format

Source file test/fixedbugs/bug484.go

Documentation: test/fixedbugs

  // 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)
  	}
  }
  

View as plain text