forked from golang/go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/compile, syscall: add //go:uintptrescapes comment, and use it
This new comment can be used to declare that the uintptr arguments to a function may be converted from pointers, and that those pointers should be considered to escape. This is used for the Call methods in dll_windows.go that take uintptr arguments, because they call Syscall. We can't treat these functions as we do syscall.Syscall, because unlike Syscall they may cause the stack to grow. For Syscall we can assume that stack arguments can remain on the stack, but for these functions we need them to escape. Fixes golang#16035. Change-Id: Ia0e5b4068c04f8d303d95ab9ea394939f1f57454 Reviewed-on: https://go-review.googlesource.com/24551 Reviewed-by: David Chase <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
- Loading branch information
1 parent
820e30f
commit bbe5da4
Showing
8 changed files
with
259 additions
and
12 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
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,54 @@ | ||
// Copyright 2016 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. | ||
|
||
package a | ||
|
||
import ( | ||
"unsafe" | ||
) | ||
|
||
func recurse(i int, s []byte) byte { | ||
s[0] = byte(i) | ||
if i == 0 { | ||
return s[i] | ||
} else { | ||
var a [1024]byte | ||
r := recurse(i-1, a[:]) | ||
return r + a[0] | ||
} | ||
} | ||
|
||
//go:uintptrescapes | ||
func F1(a uintptr) { | ||
var s [16]byte | ||
recurse(4096, s[:]) | ||
*(*int)(unsafe.Pointer(a)) = 42 | ||
} | ||
|
||
//go:uintptrescapes | ||
func F2(a ...uintptr) { | ||
var s [16]byte | ||
recurse(4096, s[:]) | ||
*(*int)(unsafe.Pointer(a[0])) = 42 | ||
} | ||
|
||
type t struct{} | ||
|
||
func GetT() *t { | ||
return &t{} | ||
} | ||
|
||
//go:uintptrescapes | ||
func (*t) M1(a uintptr) { | ||
var s [16]byte | ||
recurse(4096, s[:]) | ||
*(*int)(unsafe.Pointer(a)) = 42 | ||
} | ||
|
||
//go:uintptrescapes | ||
func (*t) M2(a ...uintptr) { | ||
var s [16]byte | ||
recurse(4096, s[:]) | ||
*(*int)(unsafe.Pointer(a[0])) = 42 | ||
} |
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,91 @@ | ||
// Copyright 2016 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. | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"sync" | ||
"unsafe" | ||
|
||
"./a" | ||
) | ||
|
||
func F1() int { | ||
var buf [1024]int | ||
a.F1(uintptr(unsafe.Pointer(&buf[0]))) | ||
return buf[0] | ||
} | ||
|
||
func F2() int { | ||
var buf [1024]int | ||
a.F2(uintptr(unsafe.Pointer(&buf[0]))) | ||
return buf[0] | ||
} | ||
|
||
var t = a.GetT() | ||
|
||
func M1() int { | ||
var buf [1024]int | ||
t.M1(uintptr(unsafe.Pointer(&buf[0]))) | ||
return buf[0] | ||
} | ||
|
||
func M2() int { | ||
var buf [1024]int | ||
t.M2(uintptr(unsafe.Pointer(&buf[0]))) | ||
return buf[0] | ||
} | ||
|
||
func main() { | ||
// Use different goroutines to force stack growth. | ||
var wg sync.WaitGroup | ||
wg.Add(4) | ||
c := make(chan bool, 4) | ||
|
||
go func() { | ||
defer wg.Done() | ||
b := F1() | ||
if b != 42 { | ||
fmt.Printf("F1: got %d, expected 42\n", b) | ||
c <- false | ||
} | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
b := F2() | ||
if b != 42 { | ||
fmt.Printf("F2: got %d, expected 42\n", b) | ||
c <- false | ||
} | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
b := M1() | ||
if b != 42 { | ||
fmt.Printf("M1: got %d, expected 42\n", b) | ||
c <- false | ||
} | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
b := M2() | ||
if b != 42 { | ||
fmt.Printf("M2: got %d, expected 42\n", b) | ||
c <- false | ||
} | ||
}() | ||
|
||
wg.Wait() | ||
|
||
select { | ||
case <-c: | ||
os.Exit(1) | ||
default: | ||
} | ||
} |
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,9 @@ | ||
// rundir | ||
|
||
// Copyright 2016 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 the go:uintptrescapes comment works as expected. | ||
|
||
package ignored |
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,31 @@ | ||
// errorcheck -0 -m -live | ||
|
||
// Copyright 2016 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 escape analysis and liveness inferred for uintptrescapes functions. | ||
|
||
package p | ||
|
||
import ( | ||
"unsafe" | ||
) | ||
|
||
//go:uintptrescapes | ||
//go:noinline | ||
func F1(a uintptr) {} // ERROR "escaping uintptr" | ||
|
||
//go:uintptrescapes | ||
//go:noinline | ||
func F2(a ...uintptr) {} // ERROR "escaping ...uintptr" "live at entry" "a does not escape" | ||
|
||
func G() { | ||
var t int // ERROR "moved to heap" | ||
F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: autotmp" "&t escapes to heap" | ||
} | ||
|
||
func H() { | ||
var v int // ERROR "moved to heap" | ||
F2(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to newobject: autotmp" "live at call to F2: autotmp" "escapes to heap" | ||
} |