Source file src/pkg/runtime/slice.go
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/math"
9 "runtime/internal/sys"
10 "unsafe"
11 )
12
13 type slice struct {
14 array unsafe.Pointer
15 len int
16 cap int
17 }
18
19
20 type notInHeapSlice struct {
21 array *notInHeap
22 len int
23 cap int
24 }
25
26 func panicmakeslicelen() {
27 panic(errorString("makeslice: len out of range"))
28 }
29
30 func panicmakeslicecap() {
31 panic(errorString("makeslice: cap out of range"))
32 }
33
34 func makeslice(et *_type, len, cap int) unsafe.Pointer {
35 mem, overflow := math.MulUintptr(et.size, uintptr(cap))
36 if overflow || mem > maxAlloc || len < 0 || len > cap {
37
38
39
40
41
42 mem, overflow := math.MulUintptr(et.size, uintptr(len))
43 if overflow || mem > maxAlloc || len < 0 {
44 panicmakeslicelen()
45 }
46 panicmakeslicecap()
47 }
48
49 return mallocgc(mem, et, true)
50 }
51
52 func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
53 len := int(len64)
54 if int64(len) != len64 {
55 panicmakeslicelen()
56 }
57
58 cap := int(cap64)
59 if int64(cap) != cap64 {
60 panicmakeslicecap()
61 }
62
63 return makeslice(et, len, cap)
64 }
65
66
67
68
69
70
71
72
73
74
75
76 func growslice(et *_type, old slice, cap int) slice {
77 if raceenabled {
78 callerpc := getcallerpc()
79 racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice))
80 }
81 if msanenabled {
82 msanread(old.array, uintptr(old.len*int(et.size)))
83 }
84
85 if cap < old.cap {
86 panic(errorString("growslice: cap out of range"))
87 }
88
89 if et.size == 0 {
90
91
92 return slice{unsafe.Pointer(&zerobase), old.len, cap}
93 }
94
95 newcap := old.cap
96 doublecap := newcap + newcap
97 if cap > doublecap {
98 newcap = cap
99 } else {
100 if old.len < 1024 {
101 newcap = doublecap
102 } else {
103
104
105 for 0 < newcap && newcap < cap {
106 newcap += newcap / 4
107 }
108
109
110 if newcap <= 0 {
111 newcap = cap
112 }
113 }
114 }
115
116 var overflow bool
117 var lenmem, newlenmem, capmem uintptr
118
119
120
121
122 switch {
123 case et.size == 1:
124 lenmem = uintptr(old.len)
125 newlenmem = uintptr(cap)
126 capmem = roundupsize(uintptr(newcap))
127 overflow = uintptr(newcap) > maxAlloc
128 newcap = int(capmem)
129 case et.size == sys.PtrSize:
130 lenmem = uintptr(old.len) * sys.PtrSize
131 newlenmem = uintptr(cap) * sys.PtrSize
132 capmem = roundupsize(uintptr(newcap) * sys.PtrSize)
133 overflow = uintptr(newcap) > maxAlloc/sys.PtrSize
134 newcap = int(capmem / sys.PtrSize)
135 case isPowerOfTwo(et.size):
136 var shift uintptr
137 if sys.PtrSize == 8 {
138
139 shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
140 } else {
141 shift = uintptr(sys.Ctz32(uint32(et.size))) & 31
142 }
143 lenmem = uintptr(old.len) << shift
144 newlenmem = uintptr(cap) << shift
145 capmem = roundupsize(uintptr(newcap) << shift)
146 overflow = uintptr(newcap) > (maxAlloc >> shift)
147 newcap = int(capmem >> shift)
148 default:
149 lenmem = uintptr(old.len) * et.size
150 newlenmem = uintptr(cap) * et.size
151 capmem, overflow = math.MulUintptr(et.size, uintptr(newcap))
152 capmem = roundupsize(capmem)
153 newcap = int(capmem / et.size)
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 if overflow || capmem > maxAlloc {
170 panic(errorString("growslice: cap out of range"))
171 }
172
173 var p unsafe.Pointer
174 if et.ptrdata == 0 {
175 p = mallocgc(capmem, nil, false)
176
177
178 memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
179 } else {
180
181 p = mallocgc(capmem, et, true)
182 if lenmem > 0 && writeBarrier.enabled {
183
184
185 bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem)
186 }
187 }
188 memmove(p, old.array, lenmem)
189
190 return slice{p, old.len, newcap}
191 }
192
193 func isPowerOfTwo(x uintptr) bool {
194 return x&(x-1) == 0
195 }
196
197 func slicecopy(to, fm slice, width uintptr) int {
198 if fm.len == 0 || to.len == 0 {
199 return 0
200 }
201
202 n := fm.len
203 if to.len < n {
204 n = to.len
205 }
206
207 if width == 0 {
208 return n
209 }
210
211 if raceenabled {
212 callerpc := getcallerpc()
213 pc := funcPC(slicecopy)
214 racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
215 racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
216 }
217 if msanenabled {
218 msanwrite(to.array, uintptr(n*int(width)))
219 msanread(fm.array, uintptr(n*int(width)))
220 }
221
222 size := uintptr(n) * width
223 if size == 1 {
224
225 *(*byte)(to.array) = *(*byte)(fm.array)
226 } else {
227 memmove(to.array, fm.array, size)
228 }
229 return n
230 }
231
232 func slicestringcopy(to []byte, fm string) int {
233 if len(fm) == 0 || len(to) == 0 {
234 return 0
235 }
236
237 n := len(fm)
238 if len(to) < n {
239 n = len(to)
240 }
241
242 if raceenabled {
243 callerpc := getcallerpc()
244 pc := funcPC(slicestringcopy)
245 racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
246 }
247 if msanenabled {
248 msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
249 }
250
251 memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n))
252 return n
253 }
254
View as plain text