Go patch committed: Pass only ptr and len to some runtime calls

Message ID CAOyqgcUi7VedkwcJWaC+Ld92iH7FnupmRG48VmgM_Mj5BuhC-Q@mail.gmail.com
State New
Headers show
Series
  • Go patch committed: Pass only ptr and len to some runtime calls
Related show

Commit Message

David Malcolm via Gcc-patches July 28, 2020, 12:06 a.m.
This patch changes the Go frontend and the libgo runtime package to
pass only ptr and len to some runtime calls, rather than passing an
entire slice.  This ports https://golang.org/cl/227163 to the Go
frontend.  This is a step toward moving up to the go1.15rc1 release.

The original change says "Some runtime calls accept a slice, but only
use ptr and len.  This change modifies most such routines to accept
only ptr and len."

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

Ian
108fdcc56ee49dd7dc8314ce5022191f406a125f

Patch

diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 12e48c19932..64a655e911e 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-8b9c7fb00ccaf1d4bcc8d581a1a4d46a35771b77
+63bc2430187efe5ff47e9c7b9cd6d40b350ee7d7
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 327f9403b39..90f860bd735 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -4157,45 +4157,43 @@  Type_conversion_expression::do_get_backend(Translate_context* context)
       go_assert(e->integer_type() != NULL);
       go_assert(this->expr_->is_variable());
 
-      Runtime::Function code;
+      Expression* buf;
+      if (this->no_escape_ && !this->no_copy_)
+        {
+          Type* byte_type = Type::lookup_integer_type("uint8");
+          Expression* buflen =
+            Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
+          Type* array_type = Type::make_array_type(byte_type, buflen);
+          buf = Expression::make_allocation(array_type, loc);
+          buf->allocation_expression()->set_allocate_on_stack();
+          buf->allocation_expression()->set_no_zero();
+        }
+      else
+        buf = Expression::make_nil(loc);
+
       if (e->integer_type()->is_byte())
         {
+	  Expression* ptr =
+	    Expression::make_slice_info(this->expr_, SLICE_INFO_VALUE_POINTER,
+					loc);
+	  Expression* len =
+	    Expression::make_slice_info(this->expr_, SLICE_INFO_LENGTH, loc);
           if (this->no_copy_)
             {
               if (gogo->debug_optimization())
                 go_debug(loc, "no copy string([]byte)");
-              Expression* ptr = Expression::make_slice_info(this->expr_,
-                                                            SLICE_INFO_VALUE_POINTER,
-                                                            loc);
-              Expression* len = Expression::make_slice_info(this->expr_,
-                                                            SLICE_INFO_LENGTH,
-                                                            loc);
               Expression* str = Expression::make_string_value(ptr, len, loc);
               return str->get_backend(context);
             }
-          code = Runtime::SLICEBYTETOSTRING;
+	  return Runtime::make_call(Runtime::SLICEBYTETOSTRING, loc, 3, buf,
+				    ptr, len)->get_backend(context);
         }
       else
         {
           go_assert(e->integer_type()->is_rune());
-          code = Runtime::SLICERUNETOSTRING;
-        }
-
-      Expression* buf;
-      if (this->no_escape_)
-        {
-          Type* byte_type = Type::lookup_integer_type("uint8");
-          Expression* buflen =
-            Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
-          Type* array_type = Type::make_array_type(byte_type, buflen);
-          buf = Expression::make_allocation(array_type, loc);
-          buf->allocation_expression()->set_allocate_on_stack();
-          buf->allocation_expression()->set_no_zero();
-        }
-      else
-        buf = Expression::make_nil(loc);
-      return Runtime::make_call(code, loc, 2, buf,
-				this->expr_)->get_backend(context);
+	  return Runtime::make_call(Runtime::SLICERUNETOSTRING, loc, 2, buf,
+				    this->expr_)->get_backend(context);
+	}
     }
   else if (type->is_slice_type() && expr_type->is_string_type())
     {
@@ -8397,8 +8395,16 @@  Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
         if (et->has_pointer())
           {
             Expression* td = Expression::make_type_descriptor(et, loc);
+	    Expression* pd =
+	      Expression::make_slice_info(arg1, SLICE_INFO_VALUE_POINTER, loc);
+	    Expression* ld =
+	      Expression::make_slice_info(arg1, SLICE_INFO_LENGTH, loc);
+	    Expression* ps =
+	      Expression::make_slice_info(arg2, SLICE_INFO_VALUE_POINTER, loc);
+	    Expression* ls =
+	      Expression::make_slice_info(arg2, SLICE_INFO_LENGTH, loc);
             ret = Runtime::make_call(Runtime::TYPEDSLICECOPY, loc,
-                                     3, td, arg1, arg2);
+                                     5, td, pd, ld, ps, ls);
           }
         else
           {
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 2ef0f94133d..a9500797b4d 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -47,7 +47,7 @@  DEF_GO_RUNTIME(INTSTRING, "runtime.intstring", P2(POINTER, INT64), R1(STRING))
 
 // Convert a []byte to a string.
 DEF_GO_RUNTIME(SLICEBYTETOSTRING, "runtime.slicebytetostring",
-	       P2(POINTER, SLICE), R1(STRING))
+	       P3(POINTER, POINTER, INT), R1(STRING))
 
 // Convert a []rune to a string.
 DEF_GO_RUNTIME(SLICERUNETOSTRING, "runtime.slicerunetostring",
@@ -249,17 +249,16 @@  DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0())
 
 
 // Copy.
-DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", P3(SLICE, SLICE, UINTPTR),
-	       R1(INT))
+DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy",
+	       P5(POINTER, INT, POINTER, INT, UINTPTR), R1(INT))
 
 // Copy from string.
-DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", P2(SLICE, STRING),
-	       R1(INT))
+DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy",
+	       P3(POINTER, INT, STRING), R1(INT))
 
 // Copy of value containing pointers.
 DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
-	       P3(TYPE, SLICE, SLICE), R1(INT))
-
+	       P5(TYPE, POINTER, INT, POINTER, INT), R1(INT))
 
 // Grow a slice for append.
 DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice",
diff --git a/libgo/go/runtime/cgocheck.go b/libgo/go/runtime/cgocheck.go
index c03bafe424c..42fdfe80280 100644
--- a/libgo/go/runtime/cgocheck.go
+++ b/libgo/go/runtime/cgocheck.go
@@ -76,23 +76,24 @@  func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
 	cgoCheckTypedBlock(typ, src, off, size)
 }
 
-// cgoCheckSliceCopy is called when copying n elements of a slice from
-// src to dst.  typ is the element type of the slice.
+// cgoCheckSliceCopy is called when copying n elements of a slice.
+// src and dst are pointers to the first element of the slice.
+// typ is the element type of the slice.
 // It throws if the program is copying slice elements that contain Go pointers
 // into non-Go memory.
 //go:nosplit
 //go:nowritebarrier
-func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
+func cgoCheckSliceCopy(typ *_type, dst, src unsafe.Pointer, n int) {
 	if typ.ptrdata == 0 {
 		return
 	}
-	if !cgoIsGoPointer(src.array) {
+	if !cgoIsGoPointer(src) {
 		return
 	}
-	if cgoIsGoPointer(dst.array) {
+	if cgoIsGoPointer(dst) {
 		return
 	}
-	p := src.array
+	p := src
 	for i := 0; i < n; i++ {
 		cgoCheckTypedBlock(typ, p, 0, typ.size)
 		p = add(p, typ.size)
diff --git a/libgo/go/runtime/mbarrier.go b/libgo/go/runtime/mbarrier.go
index e66b50d1927..a4f9b3c0350 100644
--- a/libgo/go/runtime/mbarrier.go
+++ b/libgo/go/runtime/mbarrier.go
@@ -219,16 +219,14 @@  func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size
 }
 
 //go:nosplit
-func typedslicecopy(typ *_type, dst, src slice) int {
-	n := dst.len
-	if n > src.len {
-		n = src.len
+func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe.Pointer, srcLen int) int {
+	n := dstLen
+	if n > srcLen {
+		n = srcLen
 	}
 	if n == 0 {
 		return 0
 	}
-	dstp := dst.array
-	srcp := src.array
 
 	// The compiler emits calls to typedslicecopy before
 	// instrumentation runs, so unlike the other copying and
@@ -237,19 +235,19 @@  func typedslicecopy(typ *_type, dst, src slice) int {
 	if raceenabled {
 		callerpc := getcallerpc()
 		pc := funcPC(slicecopy)
-		racewriterangepc(dstp, uintptr(n)*typ.size, callerpc, pc)
-		racereadrangepc(srcp, uintptr(n)*typ.size, callerpc, pc)
+		racewriterangepc(dstPtr, uintptr(n)*typ.size, callerpc, pc)
+		racereadrangepc(srcPtr, uintptr(n)*typ.size, callerpc, pc)
 	}
 	if msanenabled {
-		msanwrite(dstp, uintptr(n)*typ.size)
-		msanread(srcp, uintptr(n)*typ.size)
+		msanwrite(dstPtr, uintptr(n)*typ.size)
+		msanread(srcPtr, uintptr(n)*typ.size)
 	}
 
 	if writeBarrier.cgo {
-		cgoCheckSliceCopy(typ, dst, src, n)
+		cgoCheckSliceCopy(typ, dstPtr, srcPtr, n)
 	}
 
-	if dstp == srcp {
+	if dstPtr == srcPtr {
 		return n
 	}
 
@@ -259,11 +257,11 @@  func typedslicecopy(typ *_type, dst, src slice) int {
 	// before calling typedslicecopy.
 	size := uintptr(n) * typ.size
 	if writeBarrier.needed {
-		bulkBarrierPreWrite(uintptr(dstp), uintptr(srcp), size)
+		bulkBarrierPreWrite(uintptr(dstPtr), uintptr(srcPtr), size)
 	}
 	// See typedmemmove for a discussion of the race between the
 	// barrier and memmove.
-	memmove(dstp, srcp, size)
+	memmove(dstPtr, srcPtr, size)
 	return n
 }
 
@@ -293,7 +291,7 @@  func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
 		memmove(dst.array, src.array, size)
 		return n
 	}
-	return typedslicecopy(elemType, dst, src)
+	return typedslicecopy(elemType, dst.array, dst.len, src.array, src.len)
 }
 
 // typedmemclr clears the typed memory at ptr with type typ. The
diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go
index 1e864466557..5d550646715 100644
--- a/libgo/go/runtime/os_linux.go
+++ b/libgo/go/runtime/os_linux.go
@@ -207,13 +207,14 @@  func getHugePageSize() uintptr {
 	if fd < 0 {
 		return 0
 	}
-	n := read(fd, noescape(unsafe.Pointer(&numbuf[0])), int32(len(numbuf)))
+	ptr := noescape(unsafe.Pointer(&numbuf[0]))
+	n := read(fd, ptr, int32(len(numbuf)))
 	closefd(fd)
 	if n <= 0 {
 		return 0
 	}
-	l := n - 1 // remove trailing newline
-	v, ok := atoi(slicebytetostringtmp(numbuf[:l]))
+	n-- // remove trailing newline
+	v, ok := atoi(slicebytetostringtmp((*byte)(ptr), int(n)))
 	if !ok || v < 0 {
 		v = 0
 	}
diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go
index b61c2b10c7e..519735392a9 100644
--- a/libgo/go/runtime/slice.go
+++ b/libgo/go/runtime/slice.go
@@ -199,14 +199,14 @@  func isPowerOfTwo(x uintptr) bool {
 	return x&(x-1) == 0
 }
 
-func slicecopy(to, fm slice, width uintptr) int {
-	if fm.len == 0 || to.len == 0 {
+func slicecopy(toPtr unsafe.Pointer, toLen int, fmPtr unsafe.Pointer, fmLen int, width uintptr) int {
+	if fmLen == 0 || toLen == 0 {
 		return 0
 	}
 
-	n := fm.len
-	if to.len < n {
-		n = to.len
+	n := fmLen
+	if toLen < n {
+		n = toLen
 	}
 
 	if width == 0 {
@@ -216,43 +216,43 @@  func slicecopy(to, fm slice, width uintptr) int {
 	if raceenabled {
 		callerpc := getcallerpc()
 		pc := funcPC(slicecopy)
-		racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
-		racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
+		racewriterangepc(toPtr, uintptr(n*int(width)), callerpc, pc)
+		racereadrangepc(fmPtr, uintptr(n*int(width)), callerpc, pc)
 	}
 	if msanenabled {
-		msanwrite(to.array, uintptr(n*int(width)))
-		msanread(fm.array, uintptr(n*int(width)))
+		msanwrite(toPtr, uintptr(n*int(width)))
+		msanread(fmPtr, uintptr(n*int(width)))
 	}
 
 	size := uintptr(n) * width
 	if size == 1 { // common case worth about 2x to do here
 		// TODO: is this still worth it with new memmove impl?
-		*(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
+		*(*byte)(toPtr) = *(*byte)(fmPtr) // known to be a byte pointer
 	} else {
-		memmove(to.array, fm.array, size)
+		memmove(toPtr, fmPtr, size)
 	}
 	return n
 }
 
-func slicestringcopy(to []byte, fm string) int {
-	if len(fm) == 0 || len(to) == 0 {
+func slicestringcopy(toPtr *byte, toLen int, fm string) int {
+	if len(fm) == 0 || toLen == 0 {
 		return 0
 	}
 
 	n := len(fm)
-	if len(to) < n {
-		n = len(to)
+	if toLen < n {
+		n = toLen
 	}
 
 	if raceenabled {
 		callerpc := getcallerpc()
 		pc := funcPC(slicestringcopy)
-		racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
+		racewriterangepc(unsafe.Pointer(toPtr), uintptr(n), callerpc, pc)
 	}
 	if msanenabled {
-		msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
+		msanwrite(unsafe.Pointer(toPtr), uintptr(n))
 	}
 
-	memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n))
+	memmove(unsafe.Pointer(toPtr), stringStructOf(&fm).str, uintptr(n))
 	return n
 }
diff --git a/libgo/go/runtime/string.go b/libgo/go/runtime/string.go
index df4cae7bcef..7b66a1b447d 100644
--- a/libgo/go/runtime/string.go
+++ b/libgo/go/runtime/string.go
@@ -70,47 +70,50 @@  func concatstrings(buf *tmpBuf, p *string, n int) string {
 	return s
 }
 
+// slicebytetostring converts a byte slice to a string.
+// It is inserted by the compiler into generated code.
+// ptr is a pointer to the first element of the slice;
+// n is the length of the slice.
 // Buf is a fixed-size buffer for the result,
 // it is not nil if the result does not escape.
-func slicebytetostring(buf *tmpBuf, b []byte) (str string) {
-	l := len(b)
-	if l == 0 {
+func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) {
+	if n == 0 {
 		// Turns out to be a relatively common case.
 		// Consider that you want to parse out data between parens in "foo()bar",
 		// you find the indices and convert the subslice to string.
 		return ""
 	}
 	if raceenabled {
-		racereadrangepc(unsafe.Pointer(&b[0]),
-			uintptr(l),
+		racereadrangepc(unsafe.Pointer(ptr),
+			uintptr(n),
 			getcallerpc(),
 			funcPC(slicebytetostring))
 	}
 	if msanenabled {
-		msanread(unsafe.Pointer(&b[0]), uintptr(l))
+		msanread(unsafe.Pointer(ptr), uintptr(n))
 	}
-	if l == 1 {
-		stringStructOf(&str).str = unsafe.Pointer(&staticbytes[b[0]])
+	if n == 1 {
+		stringStructOf(&str).str = unsafe.Pointer(&staticbytes[*ptr])
 		stringStructOf(&str).len = 1
 		return
 	}
 
 	var p unsafe.Pointer
-	if buf != nil && len(b) <= len(buf) {
+	if buf != nil && n <= len(buf) {
 		p = unsafe.Pointer(buf)
 	} else {
-		p = mallocgc(uintptr(len(b)), nil, false)
+		p = mallocgc(uintptr(n), nil, false)
 	}
 	stringStructOf(&str).str = p
-	stringStructOf(&str).len = len(b)
-	memmove(p, (*(*slice)(unsafe.Pointer(&b))).array, uintptr(len(b)))
+	stringStructOf(&str).len = n
+	memmove(p, unsafe.Pointer(ptr), uintptr(n))
 	return
 }
 
 func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
 	if buf != nil && l <= len(buf) {
 		b = buf[:l]
-		s = slicebytetostringtmp(b)
+		s = slicebytetostringtmp(&b[0], len(b))
 	} else {
 		s, b = rawstring(l)
 	}
@@ -131,17 +134,19 @@  func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
 //   where k is []byte, T1 to Tn is a nesting of struct and array literals.
 // - Used for "<"+string(b)+">" concatenation where b is []byte.
 // - Used for string(b)=="foo" comparison where b is []byte.
-func slicebytetostringtmp(b []byte) string {
-	if raceenabled && len(b) > 0 {
-		racereadrangepc(unsafe.Pointer(&b[0]),
-			uintptr(len(b)),
+func slicebytetostringtmp(ptr *byte, n int) (str string) {
+	if raceenabled && n > 0 {
+		racereadrangepc(unsafe.Pointer(ptr),
+			uintptr(n),
 			getcallerpc(),
 			funcPC(slicebytetostringtmp))
 	}
-	if msanenabled && len(b) > 0 {
-		msanread(unsafe.Pointer(&b[0]), uintptr(len(b)))
+	if msanenabled && n > 0 {
+		msanread(unsafe.Pointer(ptr), uintptr(n))
 	}
-	return *(*string)(unsafe.Pointer(&b))
+	stringStructOf(&str).str = unsafe.Pointer(ptr)
+	stringStructOf(&str).len = n
+	return
 }
 
 func stringtoslicebyte(buf *tmpBuf, s string) []byte {
@@ -232,7 +237,7 @@  func intstring(buf *[4]byte, v int64) (s string) {
 	var b []byte
 	if buf != nil {
 		b = buf[:]
-		s = slicebytetostringtmp(b)
+		s = slicebytetostringtmp(&b[0], len(b))
 	} else {
 		s, b = rawstring(4)
 	}