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.
14 type Tintptr *int // assignable to *int
15 type Tint int // *Tint implements Tinter, interface{}
19 type Tinter interface {
23 func TestFinalizerType(t *testing.T) {
24 ch := make(chan bool, 10)
25 finalize := func(x *int) {
27 t.Errorf("finalizer %d, want %d", *x, 97531)
32 var finalizerTests = []struct {
33 convert func(*int) any
36 {func(x *int) any { return x }, func(v *int) { finalize(v) }},
37 {func(x *int) any { return Tintptr(x) }, func(v Tintptr) { finalize(v) }},
38 {func(x *int) any { return Tintptr(x) }, func(v *int) { finalize(v) }},
39 {func(x *int) any { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }},
40 {func(x *int) any { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
41 // Test case for argument spill slot.
42 // If the spill slot was not counted for the frame size, it will (incorrectly) choose
43 // call32 as the result has (exactly) 32 bytes. When the argument actually spills,
44 // it clobbers the caller's frame (likely the return PC).
45 {func(x *int) any { return x }, func(v any) [4]int64 {
46 print() // force spill
52 for _, tt := range finalizerTests {
53 done := make(chan bool, 1)
55 // allocate struct with pointer to avoid hitting tinyalloc.
56 // Otherwise we can't be sure when the allocation will
64 runtime.SetFinalizer(tt.convert(v), tt.finalizer)
74 type bigValue struct {
80 func TestFinalizerInterfaceBig(t *testing.T) {
82 done := make(chan bool, 1)
84 v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"}
86 runtime.SetFinalizer(v, func(v any) {
87 i, ok := v.(*bigValue)
89 t.Errorf("finalizer called with type %T, want *bigValue", v)
92 t.Errorf("finalizer called with %+v, want %+v", *i, old)
107 // Verify we don't crash at least. golang.org/issue/6857
108 func TestFinalizerZeroSizedStruct(t *testing.T) {
111 runtime.SetFinalizer(z, func(*Z) {})
114 func BenchmarkFinalizer(b *testing.B) {
116 b.RunParallel(func(pb *testing.PB) {
118 for i := 0; i < Batch; i++ {
122 for i := 0; i < Batch; i++ {
123 runtime.SetFinalizer(data[i], fin)
125 for i := 0; i < Batch; i++ {
126 runtime.SetFinalizer(data[i], nil)
132 func BenchmarkFinalizerRun(b *testing.B) {
133 b.RunParallel(func(pb *testing.PB) {
136 runtime.SetFinalizer(v, fin)
141 // One chunk must be exactly one sizeclass in size.
142 // It should be a sizeclass not used much by others, so we
143 // have a greater chance of finding adjacent ones.
144 // size class 19: 320 byte objects, 25 per page, 1 page alloc at a time
147 type objtype [objsize]byte
149 func adjChunks() (*objtype, *objtype) {
154 for _, d := range s {
155 if uintptr(unsafe.Pointer(c))+unsafe.Sizeof(*c) == uintptr(unsafe.Pointer(d)) {
158 if uintptr(unsafe.Pointer(d))+unsafe.Sizeof(*c) == uintptr(unsafe.Pointer(c)) {
166 // Make sure an empty slice on the stack doesn't pin the next object in memory.
167 func TestEmptySlice(t *testing.T) {
170 // the pointer inside xs points to y.
171 xs := x[objsize:] // change objsize to objsize-1 and the test passes
173 fin := make(chan bool, 1)
174 runtime.SetFinalizer(y, func(z *objtype) { fin <- true })
177 xsglobal = xs // keep empty slice alive until here
182 func adjStringChunk() (string, *objtype) {
183 b := make([]byte, objsize)
187 p := *(*uintptr)(unsafe.Pointer(&s))
188 q := uintptr(unsafe.Pointer(t))
195 // Make sure an empty string on the stack doesn't pin the next object in memory.
196 func TestEmptyString(t *testing.T) {
197 x, y := adjStringChunk()
199 ss := x[objsize:] // change objsize to objsize-1 and the test passes
200 fin := make(chan bool, 1)
201 // set finalizer on string contents of y
202 runtime.SetFinalizer(y, func(z *objtype) { fin <- true })
205 ssglobal = ss // keep 0-length string live until here
210 // Test for issue 7656.
211 func TestFinalizerOnGlobal(t *testing.T) {
212 runtime.SetFinalizer(Foo1, func(p *Object1) {})
213 runtime.SetFinalizer(Foo2, func(p *Object2) {})
214 runtime.SetFinalizer(Foo1, nil)
215 runtime.SetFinalizer(Foo2, nil)
218 type Object1 struct {
222 type Object2 struct {
231 func TestDeferKeepAlive(t *testing.T) {
238 type T *int // needs to be a pointer base type to avoid tinyalloc and its never-finalized behavior.
241 runtime.SetFinalizer(x, func(x *T) {
244 defer runtime.KeepAlive(x)
246 time.Sleep(time.Second)
248 t.Errorf("finalizer ran prematurely")