mirror of
https://github.com/golang/go
synced 2024-11-18 04:44:46 -07:00
b3bd7ab3d7
The logic for keeping arguments alive for calls to //go:uintptrescapes functions was only applying to direct function calls. This CL changes it to also apply to direct method calls, which should address most uses of Proc.Call and LazyProc.Call. It's still an open question (#34684) whether other call forms (e.g., method expressions, or indirect calls via function values, method values, or interfaces). Fixes #34474. Change-Id: I874f97145972b0e237a4c9e8926156298f4d6ce0 Reviewed-on: https://go-review.googlesource.com/c/go/+/198043 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
64 lines
1.3 KiB
Go
64 lines
1.3 KiB
Go
// run
|
|
|
|
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test that //go:uintptrescapes works for methods.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"unsafe"
|
|
)
|
|
|
|
var callback func()
|
|
|
|
//go:noinline
|
|
//go:uintptrescapes
|
|
func F(ptr uintptr) { callback() }
|
|
|
|
//go:noinline
|
|
//go:uintptrescapes
|
|
func Fv(ptrs ...uintptr) { callback() }
|
|
|
|
type T struct{}
|
|
|
|
//go:noinline
|
|
//go:uintptrescapes
|
|
func (T) M(ptr uintptr) { callback() }
|
|
|
|
//go:noinline
|
|
//go:uintptrescapes
|
|
func (T) Mv(ptrs ...uintptr) { callback() }
|
|
|
|
// Each test should pass uintptr(ptr) as an argument to a function call,
|
|
// which in turn should call callback. The callback checks that ptr is kept alive.
|
|
var tests = []func(ptr unsafe.Pointer){
|
|
func(ptr unsafe.Pointer) { F(uintptr(ptr)) },
|
|
func(ptr unsafe.Pointer) { Fv(uintptr(ptr)) },
|
|
func(ptr unsafe.Pointer) { T{}.M(uintptr(ptr)) },
|
|
func(ptr unsafe.Pointer) { T{}.Mv(uintptr(ptr)) },
|
|
}
|
|
|
|
func main() {
|
|
for i, test := range tests {
|
|
finalized := false
|
|
|
|
ptr := new([64]byte)
|
|
runtime.SetFinalizer(ptr, func(*[64]byte) {
|
|
finalized = true
|
|
})
|
|
|
|
callback = func() {
|
|
runtime.GC()
|
|
if finalized {
|
|
fmt.Printf("test #%d failed\n", i)
|
|
}
|
|
}
|
|
test(unsafe.Pointer(ptr))
|
|
}
|
|
}
|