runtime: noescape some functions/variables
authorIan Lance Taylor <ian@gcc.gnu.org>
Wed, 10 Jan 2018 05:15:52 +0000 (05:15 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 10 Jan 2018 05:15:52 +0000 (05:15 +0000)
    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

gcc/go/gofrontend/MERGE
libgo/go/runtime/panic.go
libgo/go/runtime/proc.go
libgo/go/runtime/signal_gccgo.go
libgo/go/runtime/stubs.go
libgo/go/runtime/traceback_gccgo.go

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