aboutsummaryrefslogtreecommitdiff
path: root/test/uintptrescapes3.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2019-10-01 11:22:07 -0700
committerMatthew Dempsky <mdempsky@google.com>2019-11-05 00:26:30 +0000
commitb3bd7ab3d76c694bd87dfa31f9e7ccef15ed90a7 (patch)
tree907bad812817534aacf6622f9134d95f4df08d02 /test/uintptrescapes3.go
parent6cbd737c8e4a5aa5a8e85895c5ee6ff53a358622 (diff)
downloadgo-b3bd7ab3d76c694bd87dfa31f9e7ccef15ed90a7.tar.gz
go-b3bd7ab3d76c694bd87dfa31f9e7ccef15ed90a7.zip
cmd/compile: fix //go:uintptrescapes for basic method calls
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>
Diffstat (limited to 'test/uintptrescapes3.go')
-rw-r--r--test/uintptrescapes3.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/test/uintptrescapes3.go b/test/uintptrescapes3.go
new file mode 100644
index 0000000000..92be5d1eef
--- /dev/null
+++ b/test/uintptrescapes3.go
@@ -0,0 +1,63 @@
+// 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))
+ }
+}