diff mbox series

libgo patch committed: Add some noescape cases to runtime

Message ID CAOyqgcUahBGkRrJiys0YO8SMueGbS5ReFFAibVDDvifegJHasg@mail.gmail.com
State New
Headers show
Series libgo patch committed: Add some noescape cases to runtime | expand

Commit Message

Ian Lance Taylor Jan. 10, 2018, 5:17 a.m. UTC
This libgo patch by Cherry Zhang adds some noescape cases to the
runtime package.  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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 256417)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: libgo/go/runtime/panic.go
===================================================================
--- libgo/go/runtime/panic.go	(revision 256366)
+++ libgo/go/runtime/panic.go	(working copy)
@@ -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: libgo/go/runtime/proc.go
===================================================================
--- libgo/go/runtime/proc.go	(revision 256366)
+++ libgo/go/runtime/proc.go	(working copy)
@@ -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: libgo/go/runtime/signal_gccgo.go
===================================================================
--- libgo/go/runtime/signal_gccgo.go	(revision 256366)
+++ libgo/go/runtime/signal_gccgo.go	(working copy)
@@ -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: libgo/go/runtime/stubs.go
===================================================================
--- libgo/go/runtime/stubs.go	(revision 256366)
+++ libgo/go/runtime/stubs.go	(working copy)
@@ -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, ne
 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: libgo/go/runtime/traceback_gccgo.go
===================================================================
--- libgo/go/runtime/traceback_gccgo.go	(revision 256366)
+++ libgo/go/runtime/traceback_gccgo.go	(working copy)
@@ -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)