aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/slice.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/slice.go')
-rw-r--r--libgo/go/runtime/slice.go53
1 files changed, 34 insertions, 19 deletions
diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go
index 8654aba..7c8b458 100644
--- a/libgo/go/runtime/slice.go
+++ b/libgo/go/runtime/slice.go
@@ -5,6 +5,8 @@
package runtime
import (
+ "internal/abi"
+ "internal/goarch"
"runtime/internal/math"
"runtime/internal/sys"
"unsafe"
@@ -79,12 +81,15 @@ func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsaf
if raceenabled {
callerpc := getcallerpc()
- pc := funcPC(makeslicecopy)
+ pc := abi.FuncPCABIInternal(makeslicecopy)
racereadrangepc(from, copymem, callerpc, pc)
}
if msanenabled {
msanread(from, copymem)
}
+ if asanenabled {
+ asanread(from, copymem)
+ }
memmove(to, from, copymem)
@@ -130,16 +135,15 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
}
func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
- if len == 0 {
- return
- }
-
- if ptr == nil {
- panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
+ if len < 0 {
+ panicunsafeslicelen()
}
mem, overflow := math.MulUintptr(et.size, uintptr(len))
- if overflow || mem > maxAlloc || len < 0 {
+ if overflow || mem > -uintptr(ptr) {
+ if ptr == nil {
+ panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
+ }
panicunsafeslicelen()
}
}
@@ -176,11 +180,14 @@ func panicunsafeslicelen() {
func growslice(et *_type, oldarray unsafe.Pointer, oldlen, oldcap, cap int) slice {
if raceenabled {
callerpc := getcallerpc()
- racereadrangepc(oldarray, uintptr(oldlen*int(et.size)), callerpc, funcPC(growslice))
+ racereadrangepc(oldarray, uintptr(oldlen*int(et.size)), callerpc, abi.FuncPCABIInternal(growslice))
}
if msanenabled {
msanread(oldarray, uintptr(oldlen*int(et.size)))
}
+ if asanenabled {
+ asanread(oldarray, uintptr(oldlen*int(et.size)))
+ }
if cap < oldcap {
panic(errorString("growslice: cap out of range"))
@@ -197,13 +204,17 @@ func growslice(et *_type, oldarray unsafe.Pointer, oldlen, oldcap, cap int) slic
if cap > doublecap {
newcap = cap
} else {
- if oldcap < 1024 {
+ const threshold = 256
+ if oldcap < threshold {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
- newcap += newcap / 4
+ // Transition from growing 2x for small slices
+ // to growing 1.25x for large slices. This formula
+ // gives a smooth-ish transition between the two.
+ newcap += (newcap + 3*threshold) / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
@@ -226,15 +237,15 @@ func growslice(et *_type, oldarray unsafe.Pointer, oldlen, oldcap, cap int) slic
capmem = roundupsize(uintptr(newcap))
overflow = uintptr(newcap) > maxAlloc
newcap = int(capmem)
- case et.size == sys.PtrSize:
- lenmem = uintptr(oldlen) * sys.PtrSize
- newlenmem = uintptr(cap) * sys.PtrSize
- capmem = roundupsize(uintptr(newcap) * sys.PtrSize)
- overflow = uintptr(newcap) > maxAlloc/sys.PtrSize
- newcap = int(capmem / sys.PtrSize)
+ case et.size == goarch.PtrSize:
+ lenmem = uintptr(oldlen) * goarch.PtrSize
+ newlenmem = uintptr(cap) * goarch.PtrSize
+ capmem = roundupsize(uintptr(newcap) * goarch.PtrSize)
+ overflow = uintptr(newcap) > maxAlloc/goarch.PtrSize
+ newcap = int(capmem / goarch.PtrSize)
case isPowerOfTwo(et.size):
var shift uintptr
- if sys.PtrSize == 8 {
+ if goarch.PtrSize == 8 {
// Mask shift for better code generation.
shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
} else {
@@ -312,7 +323,7 @@ func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen
size := uintptr(n) * width
if raceenabled {
callerpc := getcallerpc()
- pc := funcPC(slicecopy)
+ pc := abi.FuncPCABIInternal(slicecopy)
racereadrangepc(fromPtr, size, callerpc, pc)
racewriterangepc(toPtr, size, callerpc, pc)
}
@@ -320,6 +331,10 @@ func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen
msanread(fromPtr, size)
msanwrite(toPtr, size)
}
+ if asanenabled {
+ asanread(fromPtr, size)
+ asanwrite(toPtr, size)
+ }
if size == 1 { // common case worth about 2x to do here
// TODO: is this still worth it with new memmove impl?