1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 type sliceStruct
struct {
17 // TODO: take uintptrs instead of int64s?
18 func makeslice(t
*slicetype
, len64
int64, cap64
int64) sliceStruct
{
19 // NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
20 // but it produces a 'len out of range' error instead of a 'cap out of range' error
21 // when someone does make([]T, bignumber). 'cap out of range' is true too,
22 // but since the cap is only being supplied implicitly, saying len is clearer.
25 if len64
< 0 ||
int64(len) != len64 || t
.elem
.size
> 0 && uintptr(len) > maxmem
/uintptr(t
.elem
.size
) {
26 panic(errorString("makeslice: len out of range"))
29 if cap < len ||
int64(cap) != cap64 || t
.elem
.size
> 0 && uintptr(cap) > maxmem
/uintptr(t
.elem
.size
) {
30 panic(errorString("makeslice: cap out of range"))
32 p
:= newarray(t
.elem
, uintptr(cap))
33 return sliceStruct
{p
, len, cap}
36 // TODO: take uintptr instead of int64?
37 func growslice(t
*slicetype
, old sliceStruct
, n
int64) sliceStruct
{
39 panic(errorString("growslice: invalid n"))
42 cap64
:= int64(old
.cap) + n
45 if int64(cap) != cap64 ||
cap < old
.cap || t
.elem
.size
> 0 && uintptr(cap) > maxmem
/uintptr(t
.elem
.size
) {
46 panic(errorString("growslice: cap out of range"))
50 callerpc
:= getcallerpc(unsafe
.Pointer(&t
))
51 racereadrangepc(old
.array
, uintptr(old
.len*int(t
.elem
.size
)), callerpc
, funcPC(growslice
))
56 return sliceStruct
{old
.array
, old
.len, cap}
60 if newcap
+newcap
< cap {
75 if uintptr(newcap
) >= maxmem
/uintptr(et
.size
) {
76 panic(errorString("growslice: cap out of range"))
78 lenmem
:= uintptr(old
.len) * uintptr(et
.size
)
79 capmem
:= goroundupsize(uintptr(newcap
) * uintptr(et
.size
))
80 newcap
= int(capmem
/ uintptr(et
.size
))
82 if et
.kind
&kindNoPointers
!= 0 {
84 memclr(add(p
, lenmem
), capmem
-lenmem
)
86 // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan unitialized memory
87 p
= newarray(et
, uintptr(newcap
))
89 memmove(p
, old
.array
, lenmem
)
91 return sliceStruct
{p
, old
.len, newcap
}
94 func slicecopy(to sliceStruct
, fm sliceStruct
, width
uintptr) int {
95 if fm
.len == 0 || to
.len == 0 || width
== 0 {
105 callerpc
:= getcallerpc(unsafe
.Pointer(&to
))
106 pc
:= funcPC(slicecopy
)
107 racewriterangepc(to
.array
, uintptr(n
*int(width
)), callerpc
, pc
)
108 racereadrangepc(fm
.array
, uintptr(n
*int(width
)), callerpc
, pc
)
111 size
:= uintptr(n
) * width
112 if size
== 1 { // common case worth about 2x to do here
113 // TODO: is this still worth it with new memmove impl?
114 *(*byte)(to
.array
) = *(*byte)(fm
.array
) // known to be a byte pointer
116 memmove(to
.array
, fm
.array
, size
)
121 func slicestringcopy(to
[]byte, fm
string) int {
122 if len(fm
) == 0 ||
len(to
) == 0 {
132 callerpc
:= getcallerpc(unsafe
.Pointer(&to
))
133 pc
:= funcPC(slicestringcopy
)
134 racewriterangepc(unsafe
.Pointer(&to
[0]), uintptr(n
), callerpc
, pc
)
137 memmove(unsafe
.Pointer(&to
[0]), unsafe
.Pointer((*stringStruct
)(unsafe
.Pointer(&fm
)).str
), uintptr(n
))