Source file test/writebarrier.go

     1  // errorcheck -0 -l -d=wb
     2  
     3  // Copyright 2015 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  // Test where write barriers are and are not emitted.
     8  
     9  package p
    10  
    11  import "unsafe"
    12  
    13  func f(x **byte, y *byte) {
    14  	*x = y // no barrier (dead store)
    15  
    16  	z := y // no barrier
    17  	*x = z // ERROR "write barrier"
    18  }
    19  
    20  func f1(x *[]byte, y []byte) {
    21  	*x = y // no barrier (dead store)
    22  
    23  	z := y // no barrier
    24  	*x = z // ERROR "write barrier"
    25  }
    26  
    27  func f1a(x *[]byte, y *[]byte) {
    28  	*x = *y // ERROR "write barrier"
    29  
    30  	z := *y // no barrier
    31  	*x = z  // ERROR "write barrier"
    32  }
    33  
    34  func f2(x *interface{}, y interface{}) {
    35  	*x = y // no barrier (dead store)
    36  
    37  	z := y // no barrier
    38  	*x = z // ERROR "write barrier"
    39  }
    40  
    41  func f2a(x *interface{}, y *interface{}) {
    42  	*x = *y // no barrier (dead store)
    43  
    44  	z := y // no barrier
    45  	*x = z // ERROR "write barrier"
    46  }
    47  
    48  func f3(x *string, y string) {
    49  	*x = y // no barrier (dead store)
    50  
    51  	z := y // no barrier
    52  	*x = z // ERROR "write barrier"
    53  }
    54  
    55  func f3a(x *string, y *string) {
    56  	*x = *y // ERROR "write barrier"
    57  
    58  	z := *y // no barrier
    59  	*x = z  // ERROR "write barrier"
    60  }
    61  
    62  func f4(x *[2]string, y [2]string) {
    63  	*x = y // ERROR "write barrier"
    64  
    65  	z := y // no barrier
    66  	*x = z // ERROR "write barrier"
    67  }
    68  
    69  func f4a(x *[2]string, y *[2]string) {
    70  	*x = *y // ERROR "write barrier"
    71  
    72  	z := *y // no barrier
    73  	*x = z  // ERROR "write barrier"
    74  }
    75  
    76  type T struct {
    77  	X *int
    78  	Y int
    79  	M map[int]int
    80  }
    81  
    82  func f5(t, u *T) {
    83  	t.X = &u.Y // ERROR "write barrier"
    84  }
    85  
    86  func f6(t *T) {
    87  	t.M = map[int]int{1: 2} // ERROR "write barrier"
    88  }
    89  
    90  func f7(x, y *int) []*int {
    91  	var z [3]*int
    92  	i := 0
    93  	z[i] = x // ERROR "write barrier"
    94  	i++
    95  	z[i] = y // ERROR "write barrier"
    96  	i++
    97  	return z[:i]
    98  }
    99  
   100  func f9(x *interface{}, v *byte) {
   101  	*x = v // ERROR "write barrier"
   102  }
   103  
   104  func f10(x *byte, f func(interface{})) {
   105  	f(x)
   106  }
   107  
   108  func f11(x *unsafe.Pointer, y unsafe.Pointer) {
   109  	*x = unsafe.Pointer(uintptr(y) + 1) // ERROR "write barrier"
   110  }
   111  
   112  func f12(x []*int, y *int) []*int {
   113  	// write barrier for storing y in x's underlying array
   114  	x = append(x, y) // ERROR "write barrier"
   115  	return x
   116  }
   117  
   118  func f12a(x []int, y int) []int {
   119  	// y not a pointer, so no write barriers in this function
   120  	x = append(x, y)
   121  	return x
   122  }
   123  
   124  func f13(x []int, y *[]int) {
   125  	*y = append(x, 1) // ERROR "write barrier"
   126  }
   127  
   128  func f14(y *[]int) {
   129  	*y = append(*y, 1) // ERROR "write barrier"
   130  }
   131  
   132  type T1 struct {
   133  	X *int
   134  }
   135  
   136  func f15(x []T1, y T1) []T1 {
   137  	return append(x, y) // ERROR "write barrier"
   138  }
   139  
   140  type T8 struct {
   141  	X [8]*int
   142  }
   143  
   144  func f16(x []T8, y T8) []T8 {
   145  	return append(x, y) // ERROR "write barrier"
   146  }
   147  
   148  func t1(i interface{}) **int {
   149  	// From issue 14306, make sure we have write barriers in a type switch
   150  	// where the assigned variable escapes.
   151  	switch x := i.(type) {
   152  	case *int: // ERROR "write barrier"
   153  		return &x
   154  	}
   155  	switch y := i.(type) {
   156  	case **int: // no write barrier here
   157  		return y
   158  	}
   159  	return nil
   160  }
   161  
   162  type T17 struct {
   163  	f func(*T17)
   164  }
   165  
   166  func f17(x *T17) {
   167  	// Originally from golang.org/issue/13901, but the hybrid
   168  	// barrier requires both to have barriers.
   169  	x.f = f17                      // ERROR "write barrier"
   170  	x.f = func(y *T17) { *y = *x } // ERROR "write barrier"
   171  }
   172  
   173  type T18 struct {
   174  	a []int
   175  	s string
   176  }
   177  
   178  func f18(p *T18, x *[]int) {
   179  	p.a = p.a[:5]    // no barrier
   180  	*x = (*x)[0:5]   // no barrier
   181  	p.a = p.a[3:5]   // ERROR "write barrier"
   182  	p.a = p.a[1:2:3] // ERROR "write barrier"
   183  	p.s = p.s[8:9]   // ERROR "write barrier"
   184  	*x = (*x)[3:5]   // ERROR "write barrier"
   185  }
   186  
   187  func f19(x, y *int, i int) int {
   188  	// Constructing a temporary slice on the stack should not
   189  	// require any write barriers. See issue 14263.
   190  	a := []*int{x, y} // no barrier
   191  	return *a[i]
   192  }
   193  
   194  func f20(x, y *int, i int) []*int {
   195  	// ... but if that temporary slice escapes, then the
   196  	// write barriers are necessary.
   197  	a := []*int{x, y} // ERROR "write barrier"
   198  	return a
   199  }
   200  
   201  var x21 *int
   202  var y21 struct {
   203  	x *int
   204  }
   205  var z21 int
   206  
   207  // f21x: Global -> heap pointer updates must have write barriers.
   208  func f21a(x *int) {
   209  	x21 = x   // ERROR "write barrier"
   210  	y21.x = x // ERROR "write barrier"
   211  }
   212  
   213  func f21b(x *int) {
   214  	x21 = &z21   // ERROR "write barrier"
   215  	y21.x = &z21 // ERROR "write barrier"
   216  }
   217  
   218  func f21c(x *int) {
   219  	y21 = struct{ x *int }{x} // ERROR "write barrier"
   220  }
   221  
   222  func f22(x *int) (y *int) {
   223  	// pointer write on stack should have no write barrier.
   224  	// this is a case that the frontend failed to eliminate.
   225  	p := &y
   226  	*p = x // no barrier
   227  	return
   228  }
   229  
   230  type T23 struct {
   231  	p *int
   232  	a int
   233  }
   234  
   235  var t23 T23
   236  var i23 int
   237  
   238  // f23x: zeroing global needs write barrier for the hybrid barrier.
   239  func f23a() {
   240  	t23 = T23{} // ERROR "write barrier"
   241  }
   242  
   243  func f23b() {
   244  	// also test partial assignments
   245  	t23 = T23{a: 1} // ERROR "write barrier"
   246  }
   247  
   248  func f23c() {
   249  	t23 = T23{} // no barrier (dead store)
   250  	// also test partial assignments
   251  	t23 = T23{p: &i23} // ERROR "write barrier"
   252  }
   253  
   254  var g int
   255  
   256  func f24() **int {
   257  	p := new(*int)
   258  	*p = &g // no write barrier here
   259  	return p
   260  }
   261  func f25() []string {
   262  	return []string{"abc", "def", "ghi"} // no write barrier here
   263  }
   264  
   265  type T26 struct {
   266  	a, b, c int
   267  	d, e, f *int
   268  }
   269  
   270  var g26 int
   271  
   272  func f26(p *int) *T26 { // see issue 29573
   273  	return &T26{
   274  		a: 5,
   275  		b: 6,
   276  		c: 7,
   277  		d: &g26, // no write barrier: global ptr
   278  		e: nil,  // no write barrier: nil ptr
   279  		f: p,    // ERROR "write barrier"
   280  	}
   281  }
   282  
   283  func f27(p *int) []interface{} {
   284  	return []interface{}{
   285  		nil,         // no write barrier: zeroed memory, nil ptr
   286  		(*T26)(nil), // no write barrier: zeroed memory, type ptr & nil ptr
   287  		&g26,        // no write barrier: zeroed memory, type ptr & global ptr
   288  		7,           // no write barrier: zeroed memory, type ptr & global ptr
   289  		p,           // ERROR "write barrier"
   290  	}
   291  }
   292  
   293  var g28 [256]uint64
   294  
   295  func f28() []interface{} {
   296  	return []interface{}{
   297  		false,      // no write barrier
   298  		true,       // no write barrier
   299  		0,          // no write barrier
   300  		1,          // no write barrier
   301  		uint8(127), // no write barrier
   302  		int8(-4),   // no write barrier
   303  		&g28[5],    // no write barrier
   304  	}
   305  }
   306  

View as plain text