]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/string.go
runtime, syscall: add calls to msan functions
[gostls13.git] / src / runtime / string.go
1 // Copyright 2014 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 package runtime
6
7 import (
8         "unsafe"
9 )
10
11 // The constant is known to the compiler.
12 // There is no fundamental theory behind this number.
13 const tmpStringBufSize = 32
14
15 type tmpBuf [tmpStringBufSize]byte
16
17 // concatstrings implements a Go string concatenation x+y+z+...
18 // The operands are passed in the slice a.
19 // If buf != nil, the compiler has determined that the result does not
20 // escape the calling function, so the string data can be stored in buf
21 // if small enough.
22 func concatstrings(buf *tmpBuf, a []string) string {
23         idx := 0
24         l := 0
25         count := 0
26         for i, x := range a {
27                 n := len(x)
28                 if n == 0 {
29                         continue
30                 }
31                 if l+n < l {
32                         throw("string concatenation too long")
33                 }
34                 l += n
35                 count++
36                 idx = i
37         }
38         if count == 0 {
39                 return ""
40         }
41
42         // If there is just one string and either it is not on the stack
43         // or our result does not escape the calling frame (buf != nil),
44         // then we can return that string directly.
45         if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) {
46                 return a[idx]
47         }
48         s, b := rawstringtmp(buf, l)
49         l = 0
50         for _, x := range a {
51                 copy(b[l:], x)
52                 l += len(x)
53         }
54         return s
55 }
56
57 func concatstring2(buf *tmpBuf, a [2]string) string {
58         return concatstrings(buf, a[:])
59 }
60
61 func concatstring3(buf *tmpBuf, a [3]string) string {
62         return concatstrings(buf, a[:])
63 }
64
65 func concatstring4(buf *tmpBuf, a [4]string) string {
66         return concatstrings(buf, a[:])
67 }
68
69 func concatstring5(buf *tmpBuf, a [5]string) string {
70         return concatstrings(buf, a[:])
71 }
72
73 // Buf is a fixed-size buffer for the result,
74 // it is not nil if the result does not escape.
75 func slicebytetostring(buf *tmpBuf, b []byte) string {
76         l := len(b)
77         if l == 0 {
78                 // Turns out to be a relatively common case.
79                 // Consider that you want to parse out data between parens in "foo()bar",
80                 // you find the indices and convert the subslice to string.
81                 return ""
82         }
83         if raceenabled && l > 0 {
84                 racereadrangepc(unsafe.Pointer(&b[0]),
85                         uintptr(l),
86                         getcallerpc(unsafe.Pointer(&b)),
87                         funcPC(slicebytetostring))
88         }
89         if msanenabled && l > 0 {
90                 msanread(unsafe.Pointer(&b[0]), uintptr(l))
91         }
92         s, c := rawstringtmp(buf, l)
93         copy(c, b)
94         return s
95 }
96
97 // stringDataOnStack reports whether the string's data is
98 // stored on the current goroutine's stack.
99 func stringDataOnStack(s string) bool {
100         ptr := uintptr(stringStructOf(&s).str)
101         stk := getg().stack
102         return stk.lo <= ptr && ptr < stk.hi
103 }
104
105 func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
106         if buf != nil && l <= len(buf) {
107                 b = buf[:l]
108                 s = slicebytetostringtmp(b)
109         } else {
110                 s, b = rawstring(l)
111         }
112         return
113 }
114
115 func slicebytetostringtmp(b []byte) string {
116         // Return a "string" referring to the actual []byte bytes.
117         // This is only for use by internal compiler optimizations
118         // that know that the string form will be discarded before
119         // the calling goroutine could possibly modify the original
120         // slice or synchronize with another goroutine.
121         // First such case is a m[string(k)] lookup where
122         // m is a string-keyed map and k is a []byte.
123         // Second such case is "<"+string(b)+">" concatenation where b is []byte.
124         // Third such case is string(b)=="foo" comparison where b is []byte.
125
126         if raceenabled && len(b) > 0 {
127                 racereadrangepc(unsafe.Pointer(&b[0]),
128                         uintptr(len(b)),
129                         getcallerpc(unsafe.Pointer(&b)),
130                         funcPC(slicebytetostringtmp))
131         }
132         if msanenabled && len(b) > 0 {
133                 msanread(unsafe.Pointer(&b[0]), uintptr(len(b)))
134         }
135         return *(*string)(unsafe.Pointer(&b))
136 }
137
138 func stringtoslicebyte(buf *tmpBuf, s string) []byte {
139         var b []byte
140         if buf != nil && len(s) <= len(buf) {
141                 b = buf[:len(s)]
142         } else {
143                 b = rawbyteslice(len(s))
144         }
145         copy(b, s)
146         return b
147 }
148
149 func stringtoslicebytetmp(s string) []byte {
150         // Return a slice referring to the actual string bytes.
151         // This is only for use by internal compiler optimizations
152         // that know that the slice won't be mutated.
153         // The only such case today is:
154         // for i, c := range []byte(str)
155
156         str := stringStructOf(&s)
157         ret := slice{array: unsafe.Pointer(str.str), len: str.len, cap: str.len}
158         return *(*[]byte)(unsafe.Pointer(&ret))
159 }
160
161 func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {
162         // two passes.
163         // unlike slicerunetostring, no race because strings are immutable.
164         n := 0
165         t := s
166         for len(s) > 0 {
167                 _, k := charntorune(s)
168                 s = s[k:]
169                 n++
170         }
171         var a []rune
172         if buf != nil && n <= len(buf) {
173                 a = buf[:n]
174         } else {
175                 a = rawruneslice(n)
176         }
177         n = 0
178         for len(t) > 0 {
179                 r, k := charntorune(t)
180                 t = t[k:]
181                 a[n] = r
182                 n++
183         }
184         return a
185 }
186
187 func slicerunetostring(buf *tmpBuf, a []rune) string {
188         if raceenabled && len(a) > 0 {
189                 racereadrangepc(unsafe.Pointer(&a[0]),
190                         uintptr(len(a))*unsafe.Sizeof(a[0]),
191                         getcallerpc(unsafe.Pointer(&a)),
192                         funcPC(slicerunetostring))
193         }
194         if msanenabled && len(a) > 0 {
195                 msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
196         }
197         var dum [4]byte
198         size1 := 0
199         for _, r := range a {
200                 size1 += runetochar(dum[:], r)
201         }
202         s, b := rawstringtmp(buf, size1+3)
203         size2 := 0
204         for _, r := range a {
205                 // check for race
206                 if size2 >= size1 {
207                         break
208                 }
209                 size2 += runetochar(b[size2:], r)
210         }
211         return s[:size2]
212 }
213
214 type stringStruct struct {
215         str unsafe.Pointer
216         len int
217 }
218
219 // Variant with *byte pointer type for DWARF debugging.
220 type stringStructDWARF struct {
221         str *byte
222         len int
223 }
224
225 func stringStructOf(sp *string) *stringStruct {
226         return (*stringStruct)(unsafe.Pointer(sp))
227 }
228
229 func intstring(buf *[4]byte, v int64) string {
230         var s string
231         var b []byte
232         if buf != nil {
233                 b = buf[:]
234                 s = slicebytetostringtmp(b)
235         } else {
236                 s, b = rawstring(4)
237         }
238         n := runetochar(b, rune(v))
239         return s[:n]
240 }
241
242 // stringiter returns the index of the next
243 // rune after the rune that starts at s[k].
244 func stringiter(s string, k int) int {
245         if k >= len(s) {
246                 // 0 is end of iteration
247                 return 0
248         }
249
250         c := s[k]
251         if c < runeself {
252                 return k + 1
253         }
254
255         // multi-char rune
256         _, n := charntorune(s[k:])
257         return k + n
258 }
259
260 // stringiter2 returns the rune that starts at s[k]
261 // and the index where the next rune starts.
262 func stringiter2(s string, k int) (int, rune) {
263         if k >= len(s) {
264                 // 0 is end of iteration
265                 return 0, 0
266         }
267
268         c := s[k]
269         if c < runeself {
270                 return k + 1, rune(c)
271         }
272
273         // multi-char rune
274         r, n := charntorune(s[k:])
275         return k + n, r
276 }
277
278 // rawstring allocates storage for a new string. The returned
279 // string and byte slice both refer to the same storage.
280 // The storage is not zeroed. Callers should use
281 // b to set the string contents and then drop b.
282 func rawstring(size int) (s string, b []byte) {
283         p := mallocgc(uintptr(size), nil, flagNoScan|flagNoZero)
284
285         stringStructOf(&s).str = p
286         stringStructOf(&s).len = size
287
288         *(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}
289
290         for {
291                 ms := maxstring
292                 if uintptr(size) <= uintptr(ms) || casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
293                         return
294                 }
295         }
296 }
297
298 // rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
299 func rawbyteslice(size int) (b []byte) {
300         cap := roundupsize(uintptr(size))
301         p := mallocgc(cap, nil, flagNoScan|flagNoZero)
302         if cap != uintptr(size) {
303                 memclr(add(p, uintptr(size)), cap-uintptr(size))
304         }
305
306         *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}
307         return
308 }
309
310 // rawruneslice allocates a new rune slice. The rune slice is not zeroed.
311 func rawruneslice(size int) (b []rune) {
312         if uintptr(size) > _MaxMem/4 {
313                 throw("out of memory")
314         }
315         mem := roundupsize(uintptr(size) * 4)
316         p := mallocgc(mem, nil, flagNoScan|flagNoZero)
317         if mem != uintptr(size)*4 {
318                 memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4)
319         }
320
321         *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)}
322         return
323 }
324
325 // used by cmd/cgo
326 func gobytes(p *byte, n int) []byte {
327         if n == 0 {
328                 return make([]byte, 0)
329         }
330         x := make([]byte, n)
331         memmove(unsafe.Pointer(&x[0]), unsafe.Pointer(p), uintptr(n))
332         return x
333 }
334
335 func gostring(p *byte) string {
336         l := findnull(p)
337         if l == 0 {
338                 return ""
339         }
340         s, b := rawstring(l)
341         memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
342         return s
343 }
344
345 func gostringn(p *byte, l int) string {
346         if l == 0 {
347                 return ""
348         }
349         s, b := rawstring(l)
350         memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
351         return s
352 }
353
354 func index(s, t string) int {
355         if len(t) == 0 {
356                 return 0
357         }
358         for i := 0; i < len(s); i++ {
359                 if s[i] == t[0] && hasprefix(s[i:], t) {
360                         return i
361                 }
362         }
363         return -1
364 }
365
366 func contains(s, t string) bool {
367         return index(s, t) >= 0
368 }
369
370 func hasprefix(s, t string) bool {
371         return len(s) >= len(t) && s[:len(t)] == t
372 }
373
374 func atoi(s string) int {
375         n := 0
376         for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
377                 n = n*10 + int(s[0]) - '0'
378                 s = s[1:]
379         }
380         return n
381 }
382
383 //go:nosplit
384 func findnull(s *byte) int {
385         if s == nil {
386                 return 0
387         }
388         p := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s))
389         l := 0
390         for p[l] != 0 {
391                 l++
392         }
393         return l
394 }
395
396 func findnullw(s *uint16) int {
397         if s == nil {
398                 return 0
399         }
400         p := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(s))
401         l := 0
402         for p[l] != 0 {
403                 l++
404         }
405         return l
406 }
407
408 var maxstring uintptr = 256 // a hint for print
409
410 //go:nosplit
411 func gostringnocopy(str *byte) string {
412         ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
413         s := *(*string)(unsafe.Pointer(&ss))
414         for {
415                 ms := maxstring
416                 if uintptr(len(s)) <= ms || casuintptr(&maxstring, ms, uintptr(len(s))) {
417                         break
418                 }
419         }
420         return s
421 }
422
423 func gostringw(strw *uint16) string {
424         var buf [8]byte
425         str := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw))
426         n1 := 0
427         for i := 0; str[i] != 0; i++ {
428                 n1 += runetochar(buf[:], rune(str[i]))
429         }
430         s, b := rawstring(n1 + 4)
431         n2 := 0
432         for i := 0; str[i] != 0; i++ {
433                 // check for race
434                 if n2 >= n1 {
435                         break
436                 }
437                 n2 += runetochar(b[n2:], rune(str[i]))
438         }
439         b[n2] = 0 // for luck
440         return s[:n2]
441 }