Skip to content

Commit 6a5f1e5

Browse files
committed
runtime: simplify and optimize typedslicecopy
Currently, typedslicecopy meticulously performs a typedmemmove on every element of the slice. This probably used to be necessary because we only had an individual element's type, but now we use the heap bitmap, so we only need to know whether the type has any pointers and how big it is. Hence, this CL rewrites typedslicecopy to simply perform one bulk barrier and one memmove. This also has a side-effect of eliminating two unnecessary write barriers per slice element that were coming from updates to dstp and srcp, which were stored in the parent stack frame. However, most of the win comes from eliminating the loops. name old time/op new time/op delta BulkWriteBarrier-12 7.83ns ±10% 7.33ns ± 6% -6.45% (p=0.000 n=20+20) Updates #22460. Change-Id: Id3450e9f36cc8e0892f268319b136f0d8f5464b8 Reviewed-on: https://go-review.googlesource.com/73831 Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rick Hudson <[email protected]>
1 parent f96b95b commit 6a5f1e5

File tree

1 file changed

+6
-34
lines changed

1 file changed

+6
-34
lines changed

src/runtime/mbarrier.go

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -341,41 +341,13 @@ func typedslicecopy(typ *_type, dst, src slice) int {
341341
// compiler only emits calls to typedslicecopy for types with pointers,
342342
// and growslice and reflect_typedslicecopy check for pointers
343343
// before calling typedslicecopy.
344-
if !writeBarrier.needed {
345-
memmove(dstp, srcp, uintptr(n)*typ.size)
346-
return n
344+
size := uintptr(n) * typ.size
345+
if writeBarrier.needed {
346+
bulkBarrierPreWrite(uintptr(dstp), uintptr(srcp), size)
347347
}
348-
349-
systemstack(func() {
350-
if uintptr(srcp) < uintptr(dstp) && uintptr(srcp)+uintptr(n)*typ.size > uintptr(dstp) {
351-
// Overlap with src before dst.
352-
// Copy backward, being careful not to move dstp/srcp
353-
// out of the array they point into.
354-
dstp = add(dstp, uintptr(n-1)*typ.size)
355-
srcp = add(srcp, uintptr(n-1)*typ.size)
356-
i := 0
357-
for {
358-
typedmemmove(typ, dstp, srcp)
359-
if i++; i >= n {
360-
break
361-
}
362-
dstp = add(dstp, -typ.size)
363-
srcp = add(srcp, -typ.size)
364-
}
365-
} else {
366-
// Copy forward, being careful not to move dstp/srcp
367-
// out of the array they point into.
368-
i := 0
369-
for {
370-
typedmemmove(typ, dstp, srcp)
371-
if i++; i >= n {
372-
break
373-
}
374-
dstp = add(dstp, typ.size)
375-
srcp = add(srcp, typ.size)
376-
}
377-
}
378-
})
348+
// See typedmemmove for a discussion of the race between the
349+
// barrier and memmove.
350+
memmove(dstp, srcp, size)
379351
return n
380352
}
381353

0 commit comments

Comments
 (0)