Source file test/escape.go

     1  // run
     2  
     3  // Copyright 2009 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  package main
     8  
     9  // Test for correct heap-moving of escaped variables.
    10  // It is hard to check for the allocations, but it is easy
    11  // to check that if you call the function twice at the
    12  // same stack level, the pointers returned should be
    13  // different.
    14  
    15  var bad = false
    16  
    17  var allptr = make([]*int, 0, 100)
    18  
    19  func noalias(p, q *int, s string) {
    20  	n := len(allptr)
    21  	*p = -(n + 1)
    22  	*q = -(n + 2)
    23  	allptr = allptr[0 : n+2]
    24  	allptr[n] = p
    25  	allptr[n+1] = q
    26  	n += 2
    27  	for i := 0; i < n; i++ {
    28  		if allptr[i] != nil && *allptr[i] != -(i+1) {
    29  			println("aliased pointers", -(i + 1), *allptr[i], "after", s)
    30  			allptr[i] = nil
    31  			bad = true
    32  		}
    33  	}
    34  }
    35  
    36  func val(p, q *int, v int, s string) {
    37  	if *p != v {
    38  		println("wrong value want", v, "got", *p, "after", s)
    39  		bad = true
    40  	}
    41  	if *q != v+1 {
    42  		println("wrong value want", v+1, "got", *q, "after", s)
    43  		bad = true
    44  	}
    45  }
    46  
    47  func chk(p, q *int, v int, s string) {
    48  	val(p, q, v, s)
    49  	noalias(p, q, s)
    50  }
    51  
    52  func chkalias(p, q *int, v int, s string) {
    53  	if p != q {
    54  		println("want aliased pointers but got different after", s)
    55  		bad = true
    56  	}
    57  	if *q != v+1 {
    58  		println("wrong value want", v+1, "got", *q, "after", s)
    59  		bad = true
    60  	}
    61  }
    62  
    63  func i_escapes(x int) *int {
    64  	var i int
    65  	i = x
    66  	return &i
    67  }
    68  
    69  func j_escapes(x int) *int {
    70  	var j int = x
    71  	j = x
    72  	return &j
    73  }
    74  
    75  func k_escapes(x int) *int {
    76  	k := x
    77  	return &k
    78  }
    79  
    80  func in_escapes(x int) *int {
    81  	return &x
    82  }
    83  
    84  func send(c chan int, x int) {
    85  	c <- x
    86  }
    87  
    88  func select_escapes(x int) *int {
    89  	c := make(chan int)
    90  	go send(c, x)
    91  	select {
    92  	case req := <-c:
    93  		return &req
    94  	}
    95  	return nil
    96  }
    97  
    98  func select_escapes1(x int, y int) (*int, *int) {
    99  	c := make(chan int)
   100  	var a [2]int
   101  	var p [2]*int
   102  	a[0] = x
   103  	a[1] = y
   104  	for i := 0; i < 2; i++ {
   105  		go send(c, a[i])
   106  		select {
   107  		case req := <-c:
   108  			p[i] = &req
   109  		}
   110  	}
   111  	return p[0], p[1]
   112  }
   113  
   114  func range_escapes(x int) *int {
   115  	var a [1]int
   116  	a[0] = x
   117  	for _, v := range a {
   118  		return &v
   119  	}
   120  	return nil
   121  }
   122  
   123  // *is* aliased
   124  func range_escapes2(x, y int) (*int, *int) {
   125  	var a [2]int
   126  	var p [2]*int
   127  	a[0] = x
   128  	a[1] = y
   129  	var k, v int
   130  	for k, v = range a {
   131  		p[k] = &v
   132  	}
   133  	return p[0], p[1]
   134  }
   135  
   136  // *is* aliased
   137  func for_escapes2(x int, y int) (*int, *int) {
   138  	var p [2]*int
   139  	n := 0
   140  	i := x
   141  	for ; n < 2; i = y {
   142  		p[n] = &i
   143  		n++
   144  	}
   145  	return p[0], p[1]
   146  }
   147  
   148  func for_escapes3(x int, y int) (*int, *int) {
   149  	var f [2]func() *int
   150  	n := 0
   151  	for i := x; n < 2; i = y {
   152  		p := new(int)
   153  		*p = i
   154  		f[n] = func() *int { return p }
   155  		n++
   156  	}
   157  	return f[0](), f[1]()
   158  }
   159  
   160  func out_escapes(i int) (x int, p *int) {
   161  	x = i
   162  	p = &x // ERROR "address of out parameter"
   163  	return
   164  }
   165  
   166  func out_escapes_2(i int) (x int, p *int) {
   167  	x = i
   168  	return x, &x // ERROR "address of out parameter"
   169  }
   170  
   171  func defer1(i int) (x int) {
   172  	c := make(chan int)
   173  	go func() { x = i; c <- 1 }()
   174  	<-c
   175  	return
   176  }
   177  
   178  func main() {
   179  	p, q := i_escapes(1), i_escapes(2)
   180  	chk(p, q, 1, "i_escapes")
   181  
   182  	p, q = j_escapes(3), j_escapes(4)
   183  	chk(p, q, 3, "j_escapes")
   184  
   185  	p, q = k_escapes(5), k_escapes(6)
   186  	chk(p, q, 5, "k_escapes")
   187  
   188  	p, q = in_escapes(7), in_escapes(8)
   189  	chk(p, q, 7, "in_escapes")
   190  
   191  	p, q = select_escapes(9), select_escapes(10)
   192  	chk(p, q, 9, "select_escapes")
   193  
   194  	p, q = select_escapes1(11, 12)
   195  	chk(p, q, 11, "select_escapes1")
   196  
   197  	p, q = range_escapes(13), range_escapes(14)
   198  	chk(p, q, 13, "range_escapes")
   199  
   200  	p, q = range_escapes2(101, 102)
   201  	chkalias(p, q, 101, "range_escapes2")
   202  
   203  	p, q = for_escapes2(103, 104)
   204  	chkalias(p, q, 103, "for_escapes2")
   205  
   206  	p, q = for_escapes3(105, 106)
   207  	chk(p, q, 105, "for_escapes3")
   208  
   209  	_, p = out_escapes(15)
   210  	_, q = out_escapes(16)
   211  	chk(p, q, 15, "out_escapes")
   212  
   213  	_, p = out_escapes_2(17)
   214  	_, q = out_escapes_2(18)
   215  	chk(p, q, 17, "out_escapes_2")
   216  
   217  	x := defer1(20)
   218  	if x != 20 {
   219  		println("defer failed", x)
   220  		bad = true
   221  	}
   222  
   223  	if bad {
   224  		panic("BUG: no escape")
   225  	}
   226  }
   227  

View as plain text