aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/string.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2014-07-30 09:01:52 -0700
committerKeith Randall <khr@golang.org>2014-07-30 09:01:52 -0700
commit4aa50434e13d12eb9755a992d6d4ad93e201d624 (patch)
tree16bdb1935477b9d70d443d2b1f5c0bcb4c636682 /src/pkg/runtime/string.go
parentfe4fc94b044df5e6d08ad9e480f0bce70cc4e5d5 (diff)
downloadgo-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.go53
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
+}