github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/slice.c (about) 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. 4 5 #include "runtime.h" 6 #include "arch_GOARCH.h" 7 #include "type.h" 8 #include "typekind.h" 9 #include "malloc.h" 10 #include "race.h" 11 #include "../../cmd/ld/textflag.h" 12 13 enum 14 { 15 debug = 0 16 }; 17 18 static void makeslice1(SliceType*, intgo, intgo, Slice*); 19 static void growslice1(SliceType*, Slice, intgo, Slice *); 20 void runtime·copy(Slice to, Slice fm, uintptr width, intgo ret); 21 22 // see also unsafe·NewArray 23 // makeslice(typ *Type, len, cap int64) (ary []any); 24 void 25 runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret) 26 { 27 // NOTE: The len > MaxMem/elemsize check here is not strictly necessary, 28 // but it produces a 'len out of range' error instead of a 'cap out of range' error 29 // when someone does make([]T, bignumber). 'cap out of range' is true too, 30 // but since the cap is only being supplied implicitly, saying len is clearer. 31 // See issue 4085. 32 if(len < 0 || (intgo)len != len || t->elem->size > 0 && len > MaxMem / t->elem->size) 33 runtime·panicstring("makeslice: len out of range"); 34 35 if(cap < len || (intgo)cap != cap || t->elem->size > 0 && cap > MaxMem / t->elem->size) 36 runtime·panicstring("makeslice: cap out of range"); 37 38 makeslice1(t, len, cap, &ret); 39 40 if(debug) { 41 runtime·printf("makeslice(%S, %D, %D); ret=", 42 *t->string, len, cap); 43 runtime·printslice(ret); 44 } 45 } 46 47 // Dummy word to use as base pointer for make([]T, 0). 48 // Since you cannot take the address of such a slice, 49 // you can't tell that they all have the same base pointer. 50 uintptr runtime·zerobase; 51 52 static void 53 makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret) 54 { 55 ret->len = len; 56 ret->cap = cap; 57 ret->array = runtime·cnewarray(t->elem, cap); 58 } 59 60 // growslice(type *Type, x, []T, n int64) []T 61 void 62 runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret) 63 { 64 int64 cap; 65 void *pc; 66 67 if(n < 1) 68 runtime·panicstring("growslice: invalid n"); 69 70 cap = old.cap + n; 71 72 if((intgo)cap != cap || cap < old.cap || (t->elem->size > 0 && cap > MaxMem/t->elem->size)) 73 runtime·panicstring("growslice: cap out of range"); 74 75 if(raceenabled) { 76 pc = runtime·getcallerpc(&t); 77 runtime·racereadrangepc(old.array, old.len*t->elem->size, pc, runtime·growslice); 78 } 79 80 growslice1(t, old, cap, &ret); 81 82 FLUSH(&ret); 83 84 if(debug) { 85 runtime·printf("growslice(%S,", *t->string); 86 runtime·printslice(old); 87 runtime·printf(", new cap=%D) =", cap); 88 runtime·printslice(ret); 89 } 90 } 91 92 static void 93 growslice1(SliceType *t, Slice x, intgo newcap, Slice *ret) 94 { 95 intgo m; 96 97 m = x.cap; 98 99 // Using newcap directly for m+m < newcap handles 100 // both the case where m == 0 and also the case where 101 // m+m/4 wraps around, in which case the loop 102 // below might never terminate. 103 if(m+m < newcap) 104 m = newcap; 105 else { 106 do { 107 if(x.len < 1024) 108 m += m; 109 else 110 m += m/4; 111 } while(m < newcap); 112 } 113 makeslice1(t, x.len, m, ret); 114 runtime·memmove(ret->array, x.array, ret->len * t->elem->size); 115 } 116 117 // copy(to any, fr any, wid uintptr) int 118 #pragma textflag NOSPLIT 119 void 120 runtime·copy(Slice to, Slice fm, uintptr width, intgo ret) 121 { 122 void *pc; 123 124 if(fm.len == 0 || to.len == 0 || width == 0) { 125 ret = 0; 126 goto out; 127 } 128 129 ret = fm.len; 130 if(to.len < ret) 131 ret = to.len; 132 133 if(raceenabled) { 134 pc = runtime·getcallerpc(&to); 135 runtime·racewriterangepc(to.array, ret*width, pc, runtime·copy); 136 runtime·racereadrangepc(fm.array, ret*width, pc, runtime·copy); 137 } 138 139 if(ret == 1 && width == 1) { // common case worth about 2x to do here 140 *to.array = *fm.array; // known to be a byte pointer 141 } else { 142 runtime·memmove(to.array, fm.array, ret*width); 143 } 144 145 out: 146 FLUSH(&ret); 147 148 if(debug) { 149 runtime·prints("main·copy: to="); 150 runtime·printslice(to); 151 runtime·prints("; fm="); 152 runtime·printslice(fm); 153 runtime·prints("; width="); 154 runtime·printint(width); 155 runtime·prints("; ret="); 156 runtime·printint(ret); 157 runtime·prints("\n"); 158 } 159 } 160 161 #pragma textflag NOSPLIT 162 void 163 runtime·slicestringcopy(Slice to, String fm, intgo ret) 164 { 165 void *pc; 166 167 if(fm.len == 0 || to.len == 0) { 168 ret = 0; 169 goto out; 170 } 171 172 ret = fm.len; 173 if(to.len < ret) 174 ret = to.len; 175 176 if(raceenabled) { 177 pc = runtime·getcallerpc(&to); 178 runtime·racewriterangepc(to.array, ret, pc, runtime·slicestringcopy); 179 } 180 181 runtime·memmove(to.array, fm.str, ret); 182 183 out: 184 FLUSH(&ret); 185 } 186 187 void 188 runtime·printslice(Slice a) 189 { 190 runtime·prints("["); 191 runtime·printint(a.len); 192 runtime·prints("/"); 193 runtime·printint(a.cap); 194 runtime·prints("]"); 195 runtime·printpointer(a.array); 196 }