github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/runtime/mfinal_test.go (about) 1 // Copyright 2011 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 runtime_test 6 7 import ( 8 "runtime" 9 "testing" 10 "time" 11 "unsafe" 12 ) 13 14 type Tintptr *int // assignable to *int 15 type Tint int // *Tint implements Tinter, interface{} 16 17 func (t *Tint) m() {} 18 19 type Tinter interface { 20 m() 21 } 22 23 func TestFinalizerType(t *testing.T) { 24 if runtime.GOARCH != "amd64" { 25 t.Skipf("Skipping on non-amd64 machine") 26 } 27 if runtime.Compiler == "gccgo" { 28 t.Skip("skipping for gccgo") 29 } 30 31 ch := make(chan bool, 10) 32 finalize := func(x *int) { 33 if *x != 97531 { 34 t.Errorf("finalizer %d, want %d", *x, 97531) 35 } 36 ch <- true 37 } 38 39 var finalizerTests = []struct { 40 convert func(*int) interface{} 41 finalizer interface{} 42 }{ 43 {func(x *int) interface{} { return x }, func(v *int) { finalize(v) }}, 44 {func(x *int) interface{} { return Tintptr(x) }, func(v Tintptr) { finalize(v) }}, 45 {func(x *int) interface{} { return Tintptr(x) }, func(v *int) { finalize(v) }}, 46 {func(x *int) interface{} { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }}, 47 {func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }}, 48 } 49 50 for i, tt := range finalizerTests { 51 done := make(chan bool, 1) 52 go func() { 53 // allocate struct with pointer to avoid hitting tinyalloc. 54 // Otherwise we can't be sure when the allocation will 55 // be freed. 56 type T struct { 57 v int 58 p unsafe.Pointer 59 } 60 v := &new(T).v 61 *v = 97531 62 runtime.SetFinalizer(tt.convert(v), tt.finalizer) 63 v = nil 64 done <- true 65 }() 66 <-done 67 runtime.GC() 68 runtime.GC() 69 select { 70 case <-ch: 71 case <-time.After(time.Second * 4): 72 t.Errorf("#%d: finalizer for type %T didn't run", i, tt.finalizer) 73 } 74 } 75 } 76 77 type bigValue struct { 78 fill uint64 79 it bool 80 up string 81 } 82 83 func TestFinalizerInterfaceBig(t *testing.T) { 84 if runtime.GOARCH != "amd64" { 85 t.Skipf("Skipping on non-amd64 machine") 86 } 87 if runtime.Compiler == "gccgo" { 88 t.Skip("skipping for gccgo") 89 } 90 ch := make(chan bool) 91 done := make(chan bool, 1) 92 go func() { 93 v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"} 94 old := *v 95 runtime.SetFinalizer(v, func(v interface{}) { 96 i, ok := v.(*bigValue) 97 if !ok { 98 t.Errorf("finalizer called with type %T, want *bigValue", v) 99 } 100 if *i != old { 101 t.Errorf("finalizer called with %+v, want %+v", *i, old) 102 } 103 close(ch) 104 }) 105 v = nil 106 done <- true 107 }() 108 <-done 109 runtime.GC() 110 select { 111 case <-ch: 112 case <-time.After(4 * time.Second): 113 t.Errorf("finalizer for type *bigValue didn't run") 114 } 115 } 116 117 func fin(v *int) { 118 } 119 120 // Verify we don't crash at least. golang.org/issue/6857 121 func TestFinalizerZeroSizedStruct(t *testing.T) { 122 type Z struct{} 123 z := new(Z) 124 runtime.SetFinalizer(z, func(*Z) {}) 125 } 126 127 func BenchmarkFinalizer(b *testing.B) { 128 const Batch = 1000 129 b.RunParallel(func(pb *testing.PB) { 130 var data [Batch]*int 131 for i := 0; i < Batch; i++ { 132 data[i] = new(int) 133 } 134 for pb.Next() { 135 for i := 0; i < Batch; i++ { 136 runtime.SetFinalizer(data[i], fin) 137 } 138 for i := 0; i < Batch; i++ { 139 runtime.SetFinalizer(data[i], nil) 140 } 141 } 142 }) 143 } 144 145 func BenchmarkFinalizerRun(b *testing.B) { 146 b.RunParallel(func(pb *testing.PB) { 147 for pb.Next() { 148 v := new(int) 149 runtime.SetFinalizer(v, fin) 150 } 151 }) 152 } 153 154 // One chunk must be exactly one sizeclass in size. 155 // It should be a sizeclass not used much by others, so we 156 // have a greater chance of finding adjacent ones. 157 // size class 19: 320 byte objects, 25 per page, 1 page alloc at a time 158 const objsize = 320 159 160 type objtype [objsize]byte 161 162 func adjChunks() (*objtype, *objtype) { 163 var s []*objtype 164 165 for { 166 c := new(objtype) 167 for _, d := range s { 168 if uintptr(unsafe.Pointer(c))+unsafe.Sizeof(*c) == uintptr(unsafe.Pointer(d)) { 169 return c, d 170 } 171 if uintptr(unsafe.Pointer(d))+unsafe.Sizeof(*c) == uintptr(unsafe.Pointer(c)) { 172 return d, c 173 } 174 } 175 s = append(s, c) 176 } 177 } 178 179 // Make sure an empty slice on the stack doesn't pin the next object in memory. 180 func TestEmptySlice(t *testing.T) { 181 if runtime.Compiler == "gccgo" { 182 t.Skip("skipping for gccgo") 183 } 184 x, y := adjChunks() 185 186 // the pointer inside xs points to y. 187 xs := x[objsize:] // change objsize to objsize-1 and the test passes 188 189 fin := make(chan bool, 1) 190 runtime.SetFinalizer(y, func(z *objtype) { fin <- true }) 191 runtime.GC() 192 select { 193 case <-fin: 194 case <-time.After(4 * time.Second): 195 t.Errorf("finalizer of next object in memory didn't run") 196 } 197 xsglobal = xs // keep empty slice alive until here 198 } 199 200 var xsglobal []byte 201 202 func adjStringChunk() (string, *objtype) { 203 b := make([]byte, objsize) 204 for { 205 s := string(b) 206 t := new(objtype) 207 p := *(*uintptr)(unsafe.Pointer(&s)) 208 q := uintptr(unsafe.Pointer(t)) 209 if p+objsize == q { 210 return s, t 211 } 212 } 213 } 214 215 // Make sure an empty string on the stack doesn't pin the next object in memory. 216 func TestEmptyString(t *testing.T) { 217 if runtime.Compiler == "gccgo" { 218 t.Skip("skipping for gccgo") 219 } 220 221 x, y := adjStringChunk() 222 223 ss := x[objsize:] // change objsize to objsize-1 and the test passes 224 fin := make(chan bool, 1) 225 // set finalizer on string contents of y 226 runtime.SetFinalizer(y, func(z *objtype) { fin <- true }) 227 runtime.GC() 228 select { 229 case <-fin: 230 case <-time.After(4 * time.Second): 231 t.Errorf("finalizer of next string in memory didn't run") 232 } 233 ssglobal = ss // keep 0-length string live until here 234 } 235 236 var ssglobal string 237 238 // Test for issue 7656. 239 func TestFinalizerOnGlobal(t *testing.T) { 240 runtime.SetFinalizer(Foo1, func(p *Object1) {}) 241 runtime.SetFinalizer(Foo2, func(p *Object2) {}) 242 runtime.SetFinalizer(Foo1, nil) 243 runtime.SetFinalizer(Foo2, nil) 244 } 245 246 type Object1 struct { 247 Something []byte 248 } 249 250 type Object2 struct { 251 Something byte 252 } 253 254 var ( 255 Foo2 = &Object2{} 256 Foo1 = &Object1{} 257 )