Skip to content

Commit 63bc243

Browse files
compiler,runtime: pass only ptr and len to some runtime calls
This ports https://golang.org/cl/227163 to the Go frontend. This is a step toward moving up to the go1.15rc1 release. Original CL description: cmd/compile,runtime: pass only ptr and len to some runtime calls Some runtime calls accept a slice, but only use ptr and len. This change modifies most such routines to accept only ptr and len. After this change, the only runtime calls that accept an unnecessary cap arg are concatstrings and slicerunetostring. Neither is particularly common, and both are complicated to modify. Negligible compiler performance impact. Shrinks binaries a little. There are only a few regressions; the one I investigated was due to register allocation fluctuation. Passes 'go test -race std cmd', modulo golang/go#38265 and golang/go#38266. Wow, does that take a long time to run. file before after Δ % compile 19655024 19655152 +128 +0.001% cover 5244840 5236648 -8192 -0.156% dist 3662376 3658280 -4096 -0.112% link 6680056 6675960 -4096 -0.061% pprof 14789844 14777556 -12288 -0.083% test2json 2824744 2820648 -4096 -0.145% trace 11647876 11639684 -8192 -0.070% vet 8260472 8256376 -4096 -0.050% total 115163736 115118808 -44928 -0.039% For golang/go#36890 Change-Id: I1dc1424ccb092a9ad70472e560a743c35dd27bfc Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/245099 Reviewed-by: Cherry Zhang <[email protected]>
1 parent 8b9c7fb commit 63bc243

File tree

7 files changed

+107
-97
lines changed

7 files changed

+107
-97
lines changed

go/expressions.cc

+33-27
Original file line numberDiff line numberDiff line change
@@ -4157,45 +4157,43 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
41574157
go_assert(e->integer_type() != NULL);
41584158
go_assert(this->expr_->is_variable());
41594159

4160-
Runtime::Function code;
4160+
Expression* buf;
4161+
if (this->no_escape_ && !this->no_copy_)
4162+
{
4163+
Type* byte_type = Type::lookup_integer_type("uint8");
4164+
Expression* buflen =
4165+
Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
4166+
Type* array_type = Type::make_array_type(byte_type, buflen);
4167+
buf = Expression::make_allocation(array_type, loc);
4168+
buf->allocation_expression()->set_allocate_on_stack();
4169+
buf->allocation_expression()->set_no_zero();
4170+
}
4171+
else
4172+
buf = Expression::make_nil(loc);
4173+
41614174
if (e->integer_type()->is_byte())
41624175
{
4176+
Expression* ptr =
4177+
Expression::make_slice_info(this->expr_, SLICE_INFO_VALUE_POINTER,
4178+
loc);
4179+
Expression* len =
4180+
Expression::make_slice_info(this->expr_, SLICE_INFO_LENGTH, loc);
41634181
if (this->no_copy_)
41644182
{
41654183
if (gogo->debug_optimization())
41664184
go_debug(loc, "no copy string([]byte)");
4167-
Expression* ptr = Expression::make_slice_info(this->expr_,
4168-
SLICE_INFO_VALUE_POINTER,
4169-
loc);
4170-
Expression* len = Expression::make_slice_info(this->expr_,
4171-
SLICE_INFO_LENGTH,
4172-
loc);
41734185
Expression* str = Expression::make_string_value(ptr, len, loc);
41744186
return str->get_backend(context);
41754187
}
4176-
code = Runtime::SLICEBYTETOSTRING;
4188+
return Runtime::make_call(Runtime::SLICEBYTETOSTRING, loc, 3, buf,
4189+
ptr, len)->get_backend(context);
41774190
}
41784191
else
41794192
{
41804193
go_assert(e->integer_type()->is_rune());
4181-
code = Runtime::SLICERUNETOSTRING;
4182-
}
4183-
4184-
Expression* buf;
4185-
if (this->no_escape_)
4186-
{
4187-
Type* byte_type = Type::lookup_integer_type("uint8");
4188-
Expression* buflen =
4189-
Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
4190-
Type* array_type = Type::make_array_type(byte_type, buflen);
4191-
buf = Expression::make_allocation(array_type, loc);
4192-
buf->allocation_expression()->set_allocate_on_stack();
4193-
buf->allocation_expression()->set_no_zero();
4194-
}
4195-
else
4196-
buf = Expression::make_nil(loc);
4197-
return Runtime::make_call(code, loc, 2, buf,
4198-
this->expr_)->get_backend(context);
4194+
return Runtime::make_call(Runtime::SLICERUNETOSTRING, loc, 2, buf,
4195+
this->expr_)->get_backend(context);
4196+
}
41994197
}
42004198
else if (type->is_slice_type() && expr_type->is_string_type())
42014199
{
@@ -8397,8 +8395,16 @@ Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
83978395
if (et->has_pointer())
83988396
{
83998397
Expression* td = Expression::make_type_descriptor(et, loc);
8398+
Expression* pd =
8399+
Expression::make_slice_info(arg1, SLICE_INFO_VALUE_POINTER, loc);
8400+
Expression* ld =
8401+
Expression::make_slice_info(arg1, SLICE_INFO_LENGTH, loc);
8402+
Expression* ps =
8403+
Expression::make_slice_info(arg2, SLICE_INFO_VALUE_POINTER, loc);
8404+
Expression* ls =
8405+
Expression::make_slice_info(arg2, SLICE_INFO_LENGTH, loc);
84008406
ret = Runtime::make_call(Runtime::TYPEDSLICECOPY, loc,
8401-
3, td, arg1, arg2);
8407+
5, td, pd, ld, ps, ls);
84028408
}
84038409
else
84048410
{

go/runtime.def

+6-7
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ DEF_GO_RUNTIME(INTSTRING, "runtime.intstring", P2(POINTER, INT64), R1(STRING))
4747

4848
// Convert a []byte to a string.
4949
DEF_GO_RUNTIME(SLICEBYTETOSTRING, "runtime.slicebytetostring",
50-
P2(POINTER, SLICE), R1(STRING))
50+
P3(POINTER, POINTER, INT), R1(STRING))
5151

5252
// Convert a []rune to a string.
5353
DEF_GO_RUNTIME(SLICERUNETOSTRING, "runtime.slicerunetostring",
@@ -249,17 +249,16 @@ DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0())
249249

250250

251251
// Copy.
252-
DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", P3(SLICE, SLICE, UINTPTR),
253-
R1(INT))
252+
DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy",
253+
P5(POINTER, INT, POINTER, INT, UINTPTR), R1(INT))
254254

255255
// Copy from string.
256-
DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", P2(SLICE, STRING),
257-
R1(INT))
256+
DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy",
257+
P3(POINTER, INT, STRING), R1(INT))
258258

259259
// Copy of value containing pointers.
260260
DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
261-
P3(TYPE, SLICE, SLICE), R1(INT))
262-
261+
P5(TYPE, POINTER, INT, POINTER, INT), R1(INT))
263262

264263
// Grow a slice for append.
265264
DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice",

libgo/go/runtime/cgocheck.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,24 @@ func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
7676
cgoCheckTypedBlock(typ, src, off, size)
7777
}
7878

79-
// cgoCheckSliceCopy is called when copying n elements of a slice from
80-
// src to dst. typ is the element type of the slice.
79+
// cgoCheckSliceCopy is called when copying n elements of a slice.
80+
// src and dst are pointers to the first element of the slice.
81+
// typ is the element type of the slice.
8182
// It throws if the program is copying slice elements that contain Go pointers
8283
// into non-Go memory.
8384
//go:nosplit
8485
//go:nowritebarrier
85-
func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
86+
func cgoCheckSliceCopy(typ *_type, dst, src unsafe.Pointer, n int) {
8687
if typ.ptrdata == 0 {
8788
return
8889
}
89-
if !cgoIsGoPointer(src.array) {
90+
if !cgoIsGoPointer(src) {
9091
return
9192
}
92-
if cgoIsGoPointer(dst.array) {
93+
if cgoIsGoPointer(dst) {
9394
return
9495
}
95-
p := src.array
96+
p := src
9697
for i := 0; i < n; i++ {
9798
cgoCheckTypedBlock(typ, p, 0, typ.size)
9899
p = add(p, typ.size)

libgo/go/runtime/mbarrier.go

+13-15
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,14 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size
219219
}
220220

221221
//go:nosplit
222-
func typedslicecopy(typ *_type, dst, src slice) int {
223-
n := dst.len
224-
if n > src.len {
225-
n = src.len
222+
func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe.Pointer, srcLen int) int {
223+
n := dstLen
224+
if n > srcLen {
225+
n = srcLen
226226
}
227227
if n == 0 {
228228
return 0
229229
}
230-
dstp := dst.array
231-
srcp := src.array
232230

233231
// The compiler emits calls to typedslicecopy before
234232
// instrumentation runs, so unlike the other copying and
@@ -237,19 +235,19 @@ func typedslicecopy(typ *_type, dst, src slice) int {
237235
if raceenabled {
238236
callerpc := getcallerpc()
239237
pc := funcPC(slicecopy)
240-
racewriterangepc(dstp, uintptr(n)*typ.size, callerpc, pc)
241-
racereadrangepc(srcp, uintptr(n)*typ.size, callerpc, pc)
238+
racewriterangepc(dstPtr, uintptr(n)*typ.size, callerpc, pc)
239+
racereadrangepc(srcPtr, uintptr(n)*typ.size, callerpc, pc)
242240
}
243241
if msanenabled {
244-
msanwrite(dstp, uintptr(n)*typ.size)
245-
msanread(srcp, uintptr(n)*typ.size)
242+
msanwrite(dstPtr, uintptr(n)*typ.size)
243+
msanread(srcPtr, uintptr(n)*typ.size)
246244
}
247245

248246
if writeBarrier.cgo {
249-
cgoCheckSliceCopy(typ, dst, src, n)
247+
cgoCheckSliceCopy(typ, dstPtr, srcPtr, n)
250248
}
251249

252-
if dstp == srcp {
250+
if dstPtr == srcPtr {
253251
return n
254252
}
255253

@@ -259,11 +257,11 @@ func typedslicecopy(typ *_type, dst, src slice) int {
259257
// before calling typedslicecopy.
260258
size := uintptr(n) * typ.size
261259
if writeBarrier.needed {
262-
bulkBarrierPreWrite(uintptr(dstp), uintptr(srcp), size)
260+
bulkBarrierPreWrite(uintptr(dstPtr), uintptr(srcPtr), size)
263261
}
264262
// See typedmemmove for a discussion of the race between the
265263
// barrier and memmove.
266-
memmove(dstp, srcp, size)
264+
memmove(dstPtr, srcPtr, size)
267265
return n
268266
}
269267

@@ -293,7 +291,7 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
293291
memmove(dst.array, src.array, size)
294292
return n
295293
}
296-
return typedslicecopy(elemType, dst, src)
294+
return typedslicecopy(elemType, dst.array, dst.len, src.array, src.len)
297295
}
298296

299297
// typedmemclr clears the typed memory at ptr with type typ. The

libgo/go/runtime/os_linux.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,14 @@ func getHugePageSize() uintptr {
207207
if fd < 0 {
208208
return 0
209209
}
210-
n := read(fd, noescape(unsafe.Pointer(&numbuf[0])), int32(len(numbuf)))
210+
ptr := noescape(unsafe.Pointer(&numbuf[0]))
211+
n := read(fd, ptr, int32(len(numbuf)))
211212
closefd(fd)
212213
if n <= 0 {
213214
return 0
214215
}
215-
l := n - 1 // remove trailing newline
216-
v, ok := atoi(slicebytetostringtmp(numbuf[:l]))
216+
n-- // remove trailing newline
217+
v, ok := atoi(slicebytetostringtmp((*byte)(ptr), int(n)))
217218
if !ok || v < 0 {
218219
v = 0
219220
}

libgo/go/runtime/slice.go

+18-18
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,14 @@ func isPowerOfTwo(x uintptr) bool {
199199
return x&(x-1) == 0
200200
}
201201

202-
func slicecopy(to, fm slice, width uintptr) int {
203-
if fm.len == 0 || to.len == 0 {
202+
func slicecopy(toPtr unsafe.Pointer, toLen int, fmPtr unsafe.Pointer, fmLen int, width uintptr) int {
203+
if fmLen == 0 || toLen == 0 {
204204
return 0
205205
}
206206

207-
n := fm.len
208-
if to.len < n {
209-
n = to.len
207+
n := fmLen
208+
if toLen < n {
209+
n = toLen
210210
}
211211

212212
if width == 0 {
@@ -216,43 +216,43 @@ func slicecopy(to, fm slice, width uintptr) int {
216216
if raceenabled {
217217
callerpc := getcallerpc()
218218
pc := funcPC(slicecopy)
219-
racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
220-
racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
219+
racewriterangepc(toPtr, uintptr(n*int(width)), callerpc, pc)
220+
racereadrangepc(fmPtr, uintptr(n*int(width)), callerpc, pc)
221221
}
222222
if msanenabled {
223-
msanwrite(to.array, uintptr(n*int(width)))
224-
msanread(fm.array, uintptr(n*int(width)))
223+
msanwrite(toPtr, uintptr(n*int(width)))
224+
msanread(fmPtr, uintptr(n*int(width)))
225225
}
226226

227227
size := uintptr(n) * width
228228
if size == 1 { // common case worth about 2x to do here
229229
// TODO: is this still worth it with new memmove impl?
230-
*(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
230+
*(*byte)(toPtr) = *(*byte)(fmPtr) // known to be a byte pointer
231231
} else {
232-
memmove(to.array, fm.array, size)
232+
memmove(toPtr, fmPtr, size)
233233
}
234234
return n
235235
}
236236

237-
func slicestringcopy(to []byte, fm string) int {
238-
if len(fm) == 0 || len(to) == 0 {
237+
func slicestringcopy(toPtr *byte, toLen int, fm string) int {
238+
if len(fm) == 0 || toLen == 0 {
239239
return 0
240240
}
241241

242242
n := len(fm)
243-
if len(to) < n {
244-
n = len(to)
243+
if toLen < n {
244+
n = toLen
245245
}
246246

247247
if raceenabled {
248248
callerpc := getcallerpc()
249249
pc := funcPC(slicestringcopy)
250-
racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
250+
racewriterangepc(unsafe.Pointer(toPtr), uintptr(n), callerpc, pc)
251251
}
252252
if msanenabled {
253-
msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
253+
msanwrite(unsafe.Pointer(toPtr), uintptr(n))
254254
}
255255

256-
memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n))
256+
memmove(unsafe.Pointer(toPtr), stringStructOf(&fm).str, uintptr(n))
257257
return n
258258
}

0 commit comments

Comments
 (0)