Source file
src/runtime/slice.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/goarch"
10 "internal/runtime/math"
11 "internal/runtime/sys"
12 "unsafe"
13 )
14
15 type slice struct {
16 array unsafe.Pointer
17 len int
18 cap int
19 }
20
21
22 type notInHeapSlice struct {
23 array *notInHeap
24 len int
25 cap int
26 }
27
28 func panicmakeslicelen() {
29 panic(errorString("makeslice: len out of range"))
30 }
31
32 func panicmakeslicecap() {
33 panic(errorString("makeslice: cap out of range"))
34 }
35
36
37
38 func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer {
39 var tomem, copymem uintptr
40 if uintptr(tolen) > uintptr(fromlen) {
41 var overflow bool
42 tomem, overflow = math.MulUintptr(et.Size_, uintptr(tolen))
43 if overflow || tomem > maxAlloc || tolen < 0 {
44 panicmakeslicelen()
45 }
46 copymem = et.Size_ * uintptr(fromlen)
47 } else {
48
49
50
51 tomem = et.Size_ * uintptr(tolen)
52 copymem = tomem
53 }
54
55 var to unsafe.Pointer
56 if !et.Pointers() {
57 to = mallocgc(tomem, nil, false)
58 if copymem < tomem {
59 memclrNoHeapPointers(add(to, copymem), tomem-copymem)
60 }
61 } else {
62
63 to = mallocgc(tomem, et, true)
64 if copymem > 0 && writeBarrier.enabled {
65
66
67
68
69
70
71 bulkBarrierPreWriteSrcOnly(uintptr(to), uintptr(from), copymem, et)
72 }
73 }
74
75 if raceenabled {
76 callerpc := sys.GetCallerPC()
77 pc := abi.FuncPCABIInternal(makeslicecopy)
78 racereadrangepc(from, copymem, callerpc, pc)
79 }
80 if msanenabled {
81 msanread(from, copymem)
82 }
83 if asanenabled {
84 asanread(from, copymem)
85 }
86
87 memmove(to, from, copymem)
88
89 return to
90 }
91
92
93
94
95
96
97
98
99
100
101 func makeslice(et *_type, len, cap int) unsafe.Pointer {
102 mem, overflow := math.MulUintptr(et.Size_, uintptr(cap))
103 if overflow || mem > maxAlloc || len < 0 || len > cap {
104
105
106
107
108
109 mem, overflow := math.MulUintptr(et.Size_, uintptr(len))
110 if overflow || mem > maxAlloc || len < 0 {
111 panicmakeslicelen()
112 }
113 panicmakeslicecap()
114 }
115
116 return mallocgc(mem, et, true)
117 }
118
119 func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
120 len := int(len64)
121 if int64(len) != len64 {
122 panicmakeslicelen()
123 }
124
125 cap := int(cap64)
126 if int64(cap) != cap64 {
127 panicmakeslicecap()
128 }
129
130 return makeslice(et, len, cap)
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice {
178 oldLen := newLen - num
179 if raceenabled {
180 callerpc := sys.GetCallerPC()
181 racereadrangepc(oldPtr, uintptr(oldLen*int(et.Size_)), callerpc, abi.FuncPCABIInternal(growslice))
182 }
183 if msanenabled {
184 msanread(oldPtr, uintptr(oldLen*int(et.Size_)))
185 }
186 if asanenabled {
187 asanread(oldPtr, uintptr(oldLen*int(et.Size_)))
188 }
189
190 if newLen < 0 {
191 panic(errorString("growslice: len out of range"))
192 }
193
194 if et.Size_ == 0 {
195
196
197 return slice{unsafe.Pointer(&zerobase), newLen, newLen}
198 }
199
200 newcap := nextslicecap(newLen, oldCap)
201
202 var overflow bool
203 var lenmem, newlenmem, capmem uintptr
204
205
206
207
208 noscan := !et.Pointers()
209 switch {
210 case et.Size_ == 1:
211 lenmem = uintptr(oldLen)
212 newlenmem = uintptr(newLen)
213 capmem = roundupsize(uintptr(newcap), noscan)
214 overflow = uintptr(newcap) > maxAlloc
215 newcap = int(capmem)
216 case et.Size_ == goarch.PtrSize:
217 lenmem = uintptr(oldLen) * goarch.PtrSize
218 newlenmem = uintptr(newLen) * goarch.PtrSize
219 capmem = roundupsize(uintptr(newcap)*goarch.PtrSize, noscan)
220 overflow = uintptr(newcap) > maxAlloc/goarch.PtrSize
221 newcap = int(capmem / goarch.PtrSize)
222 case isPowerOfTwo(et.Size_):
223 var shift uintptr
224 if goarch.PtrSize == 8 {
225
226 shift = uintptr(sys.TrailingZeros64(uint64(et.Size_))) & 63
227 } else {
228 shift = uintptr(sys.TrailingZeros32(uint32(et.Size_))) & 31
229 }
230 lenmem = uintptr(oldLen) << shift
231 newlenmem = uintptr(newLen) << shift
232 capmem = roundupsize(uintptr(newcap)<<shift, noscan)
233 overflow = uintptr(newcap) > (maxAlloc >> shift)
234 newcap = int(capmem >> shift)
235 capmem = uintptr(newcap) << shift
236 default:
237 lenmem = uintptr(oldLen) * et.Size_
238 newlenmem = uintptr(newLen) * et.Size_
239 capmem, overflow = math.MulUintptr(et.Size_, uintptr(newcap))
240 capmem = roundupsize(capmem, noscan)
241 newcap = int(capmem / et.Size_)
242 capmem = uintptr(newcap) * et.Size_
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 if overflow || capmem > maxAlloc {
259 panic(errorString("growslice: len out of range"))
260 }
261
262 var p unsafe.Pointer
263 if !et.Pointers() {
264 p = mallocgc(capmem, nil, false)
265
266
267
268
269 memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
270 } else {
271
272 p = mallocgc(capmem, et, true)
273 if lenmem > 0 && writeBarrier.enabled {
274
275
276
277
278
279
280 bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(oldPtr), lenmem-et.Size_+et.PtrBytes, et)
281 }
282 }
283 memmove(p, oldPtr, lenmem)
284
285 return slice{p, newLen, newcap}
286 }
287
288
289 func nextslicecap(newLen, oldCap int) int {
290 newcap := oldCap
291 doublecap := newcap + newcap
292 if newLen > doublecap {
293 return newLen
294 }
295
296 const threshold = 256
297 if oldCap < threshold {
298 return doublecap
299 }
300 for {
301
302
303
304 newcap += (newcap + 3*threshold) >> 2
305
306
307
308
309
310 if uint(newcap) >= uint(newLen) {
311 break
312 }
313 }
314
315
316
317 if newcap <= 0 {
318 return newLen
319 }
320 return newcap
321 }
322
323
324
325
326
327
328
329
330
331
332 func reflect_growslice(et *_type, old slice, num int) slice {
333
334
335 num -= old.cap - old.len
336 new := growslice(old.array, old.cap+num, old.cap, num, et)
337
338
339
340
341 if !et.Pointers() {
342 oldcapmem := uintptr(old.cap) * et.Size_
343 newlenmem := uintptr(new.len) * et.Size_
344 memclrNoHeapPointers(add(new.array, oldcapmem), newlenmem-oldcapmem)
345 }
346 new.len = old.len
347 return new
348 }
349
350 func isPowerOfTwo(x uintptr) bool {
351 return x&(x-1) == 0
352 }
353
354
355 func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen int, width uintptr) int {
356 if fromLen == 0 || toLen == 0 {
357 return 0
358 }
359
360 n := fromLen
361 if toLen < n {
362 n = toLen
363 }
364
365 if width == 0 {
366 return n
367 }
368
369 size := uintptr(n) * width
370 if raceenabled {
371 callerpc := sys.GetCallerPC()
372 pc := abi.FuncPCABIInternal(slicecopy)
373 racereadrangepc(fromPtr, size, callerpc, pc)
374 racewriterangepc(toPtr, size, callerpc, pc)
375 }
376 if msanenabled {
377 msanread(fromPtr, size)
378 msanwrite(toPtr, size)
379 }
380 if asanenabled {
381 asanread(fromPtr, size)
382 asanwrite(toPtr, size)
383 }
384
385 if size == 1 {
386
387 *(*byte)(toPtr) = *(*byte)(fromPtr)
388 } else {
389 memmove(toPtr, fromPtr, size)
390 }
391 return n
392 }
393
394
395 func bytealg_MakeNoZero(len int) []byte {
396 if uintptr(len) > maxAlloc {
397 panicmakeslicelen()
398 }
399 cap := roundupsize(uintptr(len), true)
400 return unsafe.Slice((*byte)(mallocgc(uintptr(cap), nil, false)), cap)[:len]
401 }
402
View as plain text