Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Showing
3 changed files
with
95 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) | ||
} | ||
} |