bug484.go 1.67 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// 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"

26
//go:noinline
27 28 29 30 31
func f() interface{} {
	runtime.GC()
	return nil
}

32
//go:noinline
33 34 35 36 37 38 39 40 41 42 43
func g() {
	var s interface{}
	_ = func() {
		s := f()
		_ = s
	}
	s = f()
	useiface(s)
	useiface(s)
}

44
//go:noinline
45 46 47
func useiface(x interface{}) {
}

48
//go:noinline
49 50 51 52 53
func h() {
	var x [16]uintptr
	for i := range x {
		x[i] = 1
	}
54

55 56 57 58 59 60
	useint(x[0])
	useint(x[1])
	useint(x[2])
	useint(x[3])
}

61
//go:noinline
62 63 64 65 66 67 68 69 70 71 72 73 74 75
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 {
76
		big(x - 1)
77 78
	}
}