Home | History | Annotate | Download | only in gc
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package gc
      6 
      7 import "testing"
      8 
      9 type T struct {
     10 	x [2]int64 // field that will be clobbered. Also makes type not SSAable.
     11 	p *byte    // has a pointer
     12 }
     13 
     14 //go:noinline
     15 func makeT() T {
     16 	return T{}
     17 }
     18 
     19 var g T
     20 
     21 var sink interface{}
     22 
     23 func TestIssue15854(t *testing.T) {
     24 	for i := 0; i < 10000; i++ {
     25 		if g.x[0] != 0 {
     26 			t.Fatalf("g.x[0] clobbered with %x\n", g.x[0])
     27 		}
     28 		// The bug was in the following assignment. The return
     29 		// value of makeT() is not copied out of the args area of
     30 		// stack frame in a timely fashion. So when write barriers
     31 		// are enabled, the marshaling of the args for the write
     32 		// barrier call clobbers the result of makeT() before it is
     33 		// read by the write barrier code.
     34 		g = makeT()
     35 		sink = make([]byte, 1000) // force write barriers to eventually happen
     36 	}
     37 }
     38 func TestIssue15854b(t *testing.T) {
     39 	const N = 10000
     40 	a := make([]T, N)
     41 	for i := 0; i < N; i++ {
     42 		a = append(a, makeT())
     43 		sink = make([]byte, 1000) // force write barriers to eventually happen
     44 	}
     45 	for i, v := range a {
     46 		if v.x[0] != 0 {
     47 			t.Fatalf("a[%d].x[0] clobbered with %x\n", i, v.x[0])
     48 		}
     49 	}
     50 }
     51