diff options
| author | Keith Randall <khr@golang.org> | 2014-07-30 09:01:52 -0700 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2014-07-30 09:01:52 -0700 |
| commit | 4aa50434e13d12eb9755a992d6d4ad93e201d624 (patch) | |
| tree | 16bdb1935477b9d70d443d2b1f5c0bcb4c636682 /src/pkg/runtime/string.go | |
| parent | fe4fc94b044df5e6d08ad9e480f0bce70cc4e5d5 (diff) | |
| download | go-4aa50434e13d12eb9755a992d6d4ad93e201d624.tar.xz | |
runtime: rewrite malloc in Go.
This change introduces gomallocgc, a Go clone of mallocgc.
Only a few uses have been moved over, so there are still
lots of uses from C. Many of these C uses will be moved
over to Go (e.g. in slice.goc), but probably not all.
What should remain of C's mallocgc is an open question.
LGTM=rsc, dvyukov
R=rsc, khr, dave, bradfitz, dvyukov
CC=golang-codereviews
https://golang.org/cl/108840046
Diffstat (limited to 'src/pkg/runtime/string.go')
| -rw-r--r-- | src/pkg/runtime/string.go | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/pkg/runtime/string.go b/src/pkg/runtime/string.go index 475c837e36..c5b0917482 100644 --- a/src/pkg/runtime/string.go +++ b/src/pkg/runtime/string.go @@ -202,3 +202,56 @@ func stringiter2(s string, k int) (int, rune) { r, n := charntorune(s[k:]) return k + n, r } + +// rawstring allocates storage for a new string. The returned +// string and byte slice both refer to the same storage. +// The storage is not zeroed. Callers should use +// b to set the string contents and then drop b. +func rawstring(size int) (s string, b []byte) { + p := gomallocgc(uintptr(size), nil, flagNoScan|flagNoZero) + + (*stringStruct)(unsafe.Pointer(&s)).str = p + (*stringStruct)(unsafe.Pointer(&s)).len = size + + (*slice)(unsafe.Pointer(&b)).array = (*uint8)(p) + (*slice)(unsafe.Pointer(&b)).len = uint(size) + (*slice)(unsafe.Pointer(&b)).cap = uint(size) + + for { + ms := maxstring + if uintptr(size) <= uintptr(ms) || gocasx((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) { + return + } + } +} + +// rawbyteslice allocates a new byte slice. The byte slice is not zeroed. +func rawbyteslice(size int) (b []byte) { + cap := goroundupsize(uintptr(size)) + p := gomallocgc(cap, nil, flagNoScan|flagNoZero) + if cap != uintptr(size) { + memclr(add(p, uintptr(size)), cap-uintptr(size)) + } + + (*slice)(unsafe.Pointer(&b)).array = (*uint8)(p) + (*slice)(unsafe.Pointer(&b)).len = uint(size) + (*slice)(unsafe.Pointer(&b)).cap = uint(cap) + return +} + +// rawruneslice allocates a new rune slice. The rune slice is not zeroed. +func rawruneslice(size int) (b []rune) { + if uintptr(size) > maxMem/4 { + gothrow("out of memory") + } + mem := goroundupsize(uintptr(size) * 4) + p := gomallocgc(mem, nil, flagNoScan|flagNoZero) + if mem != uintptr(size)*4 { + memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4) + } + + (*slice)(unsafe.Pointer(&b)).array = (*uint8)(p) + (*slice)(unsafe.Pointer(&b)).len = uint(size) + (*slice)(unsafe.Pointer(&b)).cap = uint(mem / 4) + return +} |
