Commit e4876be5 by Ian Lance Taylor

runtime: noescape some functions/variables

    
    This is in preparation of turning on escape analysis for the
    runtime.
    
    - In gccgo, systemstack is implemented with mcall, which is not
      go:noescape. Wrap the closure in noescape so the escape analysis
      does not think it escapes.
    
    - Mark some C functions go:noescape. They do not leak arguments.
    
    - Use noescape function to make a few local variables' addresses
      not escape. The escape analysis cannot figure out because they
      are assigned to pointer indirections.
    
    Reviewed-on: https://go-review.googlesource.com/86244

From-SVN: r256418
parent fe9e1702
8e20ba6b6c4906f2f0be4b0a1515d11e0f41fb29 5cae6a4e0849a3586ee7ce9c915c1520a17db982
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -201,7 +201,7 @@ func deferreturn(frame *bool) { ...@@ -201,7 +201,7 @@ func deferreturn(frame *bool) {
// The gc compiler does this using assembler // The gc compiler does this using assembler
// code in jmpdefer. // code in jmpdefer.
var fn func(unsafe.Pointer) var fn func(unsafe.Pointer)
*(*uintptr)(unsafe.Pointer(&fn)) = uintptr(unsafe.Pointer(&pfn)) *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn)))
fn(d.arg) fn(d.arg)
} }
...@@ -264,7 +264,7 @@ func checkdefer(frame *bool) { ...@@ -264,7 +264,7 @@ func checkdefer(frame *bool) {
var p _panic var p _panic
p.isforeign = true p.isforeign = true
p.link = gp._panic p.link = gp._panic
gp._panic = &p gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
for { for {
d := gp._defer d := gp._defer
if d == nil || d.frame != frame || d.pfn == 0 { if d == nil || d.frame != frame || d.pfn == 0 {
...@@ -275,7 +275,7 @@ func checkdefer(frame *bool) { ...@@ -275,7 +275,7 @@ func checkdefer(frame *bool) {
gp._defer = d.link gp._defer = d.link
var fn func(unsafe.Pointer) var fn func(unsafe.Pointer)
*(*uintptr)(unsafe.Pointer(&fn)) = uintptr(unsafe.Pointer(&pfn)) *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn)))
fn(d.arg) fn(d.arg)
freedefer(d) freedefer(d)
...@@ -368,7 +368,7 @@ func Goexit() { ...@@ -368,7 +368,7 @@ func Goexit() {
d.pfn = 0 d.pfn = 0
var fn func(unsafe.Pointer) var fn func(unsafe.Pointer)
*(*uintptr)(unsafe.Pointer(&fn)) = uintptr(unsafe.Pointer(&pfn)) *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn)))
fn(d.arg) fn(d.arg)
if gp._defer != d { if gp._defer != d {
...@@ -491,7 +491,7 @@ func gopanic(e interface{}) { ...@@ -491,7 +491,7 @@ func gopanic(e interface{}) {
d._panic = p d._panic = p
var fn func(unsafe.Pointer) var fn func(unsafe.Pointer)
*(*uintptr)(unsafe.Pointer(&fn)) = uintptr(unsafe.Pointer(&pfn)) *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn)))
fn(d.arg) fn(d.arg)
if gp._defer != d { if gp._defer != d {
......
...@@ -46,7 +46,11 @@ import ( ...@@ -46,7 +46,11 @@ import (
// C functions for thread and context management. // C functions for thread and context management.
func newosproc(*m) func newosproc(*m)
//go:noescape
func malg(bool, bool, *unsafe.Pointer, *uintptr) *g func malg(bool, bool, *unsafe.Pointer, *uintptr) *g
//go:noescape
func resetNewG(*g, *unsafe.Pointer, *uintptr) func resetNewG(*g, *unsafe.Pointer, *uintptr)
func gogo(*g) func gogo(*g)
func setGContext() func setGContext()
......
...@@ -13,24 +13,31 @@ import ( ...@@ -13,24 +13,31 @@ import (
// Functions for gccgo to support signal handling. In the gc runtime // Functions for gccgo to support signal handling. In the gc runtime
// these are written in OS-specific files and in assembler. // these are written in OS-specific files and in assembler.
//go:noescape
//extern sigaction //extern sigaction
func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32 func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32
//go:noescape
//extern sigprocmask //extern sigprocmask
func sigprocmask(how int32, set *sigset, oldset *sigset) int32 func sigprocmask(how int32, set *sigset, oldset *sigset) int32
//go:noescape
//extern sigfillset //extern sigfillset
func sigfillset(set *sigset) int32 func sigfillset(set *sigset) int32
//go:noescape
//extern sigemptyset //extern sigemptyset
func sigemptyset(set *sigset) int32 func sigemptyset(set *sigset) int32
//go:noescape
//extern sigaddset //extern sigaddset
func c_sigaddset(set *sigset, signum uint32) int32 func c_sigaddset(set *sigset, signum uint32) int32
//go:noescape
//extern sigdelset //extern sigdelset
func c_sigdelset(set *sigset, signum uint32) int32 func c_sigdelset(set *sigset, signum uint32) int32
//go:noescape
//extern sigaltstack //extern sigaltstack
func sigaltstack(ss *_stack_t, oss *_stack_t) int32 func sigaltstack(ss *_stack_t, oss *_stack_t) int32
...@@ -43,6 +50,7 @@ func getpid() _pid_t ...@@ -43,6 +50,7 @@ func getpid() _pid_t
//extern kill //extern kill
func kill(pid _pid_t, sig uint32) int32 func kill(pid _pid_t, sig uint32) int32
//go:noescape
//extern setitimer //extern setitimer
func setitimer(which int32, new *_itimerval, old *_itimerval) int32 func setitimer(which int32, new *_itimerval, old *_itimerval) int32
......
...@@ -60,10 +60,11 @@ func systemstack(fn func()) { ...@@ -60,10 +60,11 @@ func systemstack(fn func()) {
if gp == mp.g0 || gp == mp.gsignal { if gp == mp.g0 || gp == mp.gsignal {
fn() fn()
} else if gp == mp.curg { } else if gp == mp.curg {
mcall(func(origg *g) { fn1 := func(origg *g) {
fn() fn()
gogo(origg) gogo(origg)
}) }
mcall(*(*func(*g))(noescape(unsafe.Pointer(&fn1))))
} else { } else {
badsystemstack() badsystemstack()
} }
...@@ -160,6 +161,7 @@ func breakpoint() ...@@ -160,6 +161,7 @@ func breakpoint()
func asminit() {} func asminit() {}
//go:linkname reflectcall reflect.call //go:linkname reflectcall reflect.call
//go:noescape
func reflectcall(fntype *functype, fn *funcval, isInterface, isMethod bool, params, results *unsafe.Pointer) func reflectcall(fntype *functype, fn *funcval, isInterface, isMethod bool, params, results *unsafe.Pointer)
func procyield(cycles uint32) func procyield(cycles uint32)
...@@ -355,7 +357,10 @@ func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) { ...@@ -355,7 +357,10 @@ func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
func getSigtramp() uintptr func getSigtramp() uintptr
// The sa_handler field is generally hidden in a union, so use C accessors. // The sa_handler field is generally hidden in a union, so use C accessors.
//go:noescape
func getSigactionHandler(*_sigaction) uintptr func getSigactionHandler(*_sigaction) uintptr
//go:noescape
func setSigactionHandler(*_sigaction, uintptr) func setSigactionHandler(*_sigaction, uintptr)
// Retrieve fields from the siginfo_t and ucontext_t pointers passed // Retrieve fields from the siginfo_t and ucontext_t pointers passed
......
...@@ -9,7 +9,7 @@ package runtime ...@@ -9,7 +9,7 @@ package runtime
import ( import (
"runtime/internal/sys" "runtime/internal/sys"
_ "unsafe" // for go:linkname "unsafe"
) )
func printcreatedby(gp *g) { func printcreatedby(gp *g) {
...@@ -46,6 +46,7 @@ type location struct { ...@@ -46,6 +46,7 @@ type location struct {
lineno int lineno int
} }
//go:noescape
//extern runtime_callers //extern runtime_callers
func c_callers(skip int32, locbuf *location, max int32, keepThunks bool) int32 func c_callers(skip int32, locbuf *location, max int32, keepThunks bool) int32
...@@ -185,7 +186,7 @@ func tracebackothers(me *g) { ...@@ -185,7 +186,7 @@ func tracebackothers(me *g) {
if gp != nil && gp != me { if gp != nil && gp != me {
print("\n") print("\n")
goroutineheader(gp) goroutineheader(gp)
gp.traceback = &tb gp.traceback = (*tracebackg)(noescape(unsafe.Pointer(&tb)))
getTraceback(me, gp) getTraceback(me, gp)
printtrace(tb.locbuf[:tb.c], nil) printtrace(tb.locbuf[:tb.c], nil)
printcreatedby(gp) printcreatedby(gp)
...@@ -219,7 +220,7 @@ func tracebackothers(me *g) { ...@@ -219,7 +220,7 @@ func tracebackothers(me *g) {
print("\tgoroutine in C code; stack unavailable\n") print("\tgoroutine in C code; stack unavailable\n")
printcreatedby(gp) printcreatedby(gp)
} else { } else {
gp.traceback = &tb gp.traceback = (*tracebackg)(noescape(unsafe.Pointer(&tb)))
getTraceback(me, gp) getTraceback(me, gp)
printtrace(tb.locbuf[:tb.c], nil) printtrace(tb.locbuf[:tb.c], nil)
printcreatedby(gp) printcreatedby(gp)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment