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 if runtime
.GOARCH
!= "amd64" {
25 t
.Skipf("Skipping on non-amd64 machine")
28 ch
:= make(chan bool, 10)
29 finalize
:= func(x
*int) {
31 t
.Errorf("finalizer %d, want %d", *x
, 97531)
36 var finalizerTests
= []struct {
37 convert
func(*int) interface{}
40 {func(x
*int) interface{} { return x
}, func(v
*int) { finalize(v
) }},
41 {func(x
*int) interface{} { return Tintptr(x
) }, func(v Tintptr
) { finalize(v
) }},
42 {func(x
*int) interface{} { return Tintptr(x
) }, func(v
*int) { finalize(v
) }},
43 {func(x
*int) interface{} { return (*Tint
)(x
) }, func(v
*Tint
) { finalize((*int)(v
)) }},
44 {func(x
*int) interface{} { return (*Tint
)(x
) }, func(v Tinter
) { finalize((*int)(v
.(*Tint
))) }},
47 for _
, tt
:= range finalizerTests
{
48 done
:= make(chan bool, 1)
52 runtime
.SetFinalizer(tt
.convert(v
), tt
.finalizer
)
60 case <-time
.After(time
.Second
* 4):
61 t
.Errorf("finalizer for type %T didn't run", tt
.finalizer
)
66 type bigValue
struct {
72 func TestFinalizerInterfaceBig(t
*testing
.T
) {
73 if runtime
.GOARCH
!= "amd64" {
74 t
.Skipf("Skipping on non-amd64 machine")
77 done
:= make(chan bool, 1)
79 v
:= &bigValue
{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"}
81 runtime
.SetFinalizer(v
, func(v
interface{}) {
82 i
, ok
:= v
.(*bigValue
)
84 t
.Errorf("finalizer called with type %T, want *bigValue", v
)
87 t
.Errorf("finalizer called with %+v, want %+v", *i
, old
)
98 case <-time
.After(4 * time
.Second
):
99 t
.Errorf("finalizer for type *bigValue didn't run")
106 // Verify we don't crash at least. golang.org/issue/6857
107 func TestFinalizerZeroSizedStruct(t
*testing
.T
) {
110 runtime
.SetFinalizer(z
, func(*Z
) {})
113 func BenchmarkFinalizer(b
*testing
.B
) {
115 b
.RunParallel(func(pb
*testing
.PB
) {
117 for i
:= 0; i
< Batch
; i
++ {
121 for i
:= 0; i
< Batch
; i
++ {
122 runtime
.SetFinalizer(data
[i
], fin
)
124 for i
:= 0; i
< Batch
; i
++ {
125 runtime
.SetFinalizer(data
[i
], nil)
131 func BenchmarkFinalizerRun(b
*testing
.B
) {
132 b
.RunParallel(func(pb
*testing
.PB
) {
135 runtime
.SetFinalizer(v
, fin
)
140 // One chunk must be exactly one sizeclass in size.
141 // It should be a sizeclass not used much by others, so we
142 // have a greater chance of finding adjacent ones.
143 // size class 19: 320 byte objects, 25 per page, 1 page alloc at a time
146 type objtype
[objsize
]byte
148 func adjChunks() (*objtype
, *objtype
) {
153 for _
, d
:= range s
{
154 if uintptr(unsafe
.Pointer(c
))+unsafe
.Sizeof(*c
) == uintptr(unsafe
.Pointer(d
)) {
157 if uintptr(unsafe
.Pointer(d
))+unsafe
.Sizeof(*c
) == uintptr(unsafe
.Pointer(c
)) {
165 // Make sure an empty slice on the stack doesn't pin the next object in memory.
166 func TestEmptySlice(t
*testing
.T
) {
167 if true { // disable until bug 7564 is fixed.
172 // the pointer inside xs points to y.
173 xs
:= x
[objsize
:] // change objsize to objsize-1 and the test passes
175 fin
:= make(chan bool, 1)
176 runtime
.SetFinalizer(y
, func(z
*objtype
) { fin
<- true })
180 case <-time
.After(4 * time
.Second
):
181 t
.Errorf("finalizer of next object in memory didn't run")
183 xsglobal
= xs
// keep empty slice alive until here
188 func adjStringChunk() (string, *objtype
) {
189 b
:= make([]byte, objsize
)
193 p
:= *(*uintptr)(unsafe
.Pointer(&s
))
194 q
:= uintptr(unsafe
.Pointer(t
))
201 // Make sure an empty string on the stack doesn't pin the next object in memory.
202 func TestEmptyString(t
*testing
.T
) {
203 if runtime
.Compiler
== "gccgo" {
204 t
.Skip("skipping for gccgo")
207 x
, y
:= adjStringChunk()
209 ss
:= x
[objsize
:] // change objsize to objsize-1 and the test passes
210 fin
:= make(chan bool, 1)
211 // set finalizer on string contents of y
212 runtime
.SetFinalizer(y
, func(z
*objtype
) { fin
<- true })
216 case <-time
.After(4 * time
.Second
):
217 t
.Errorf("finalizer of next string in memory didn't run")
219 ssglobal
= ss
// keep 0-length string live until here
224 // Test for issue 7656.
225 func TestFinalizerOnGlobal(t
*testing
.T
) {
226 runtime
.SetFinalizer(Foo1
, func(p
*Object1
) {})
227 runtime
.SetFinalizer(Foo2
, func(p
*Object2
) {})
228 runtime
.SetFinalizer(Foo1
, nil)
229 runtime
.SetFinalizer(Foo2
, nil)
232 type Object1
struct {
236 type Object2
struct {