summaryrefslogtreecommitdiff
path: root/test/slicecap.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-08-25 14:38:19 -0400
committerRuss Cox <rsc@golang.org>2014-08-25 14:38:19 -0400
commit588ffed86c777b6270c341fffadbbfb82f2c6a9c (patch)
tree4e5302f4267cc27b1bc1e04c5c4469f577f0ec0d /test/slicecap.go
parente4b65ea6a0b2755b284d20e1822ea2db8df9a7e6 (diff)
downloadgo-588ffed86c777b6270c341fffadbbfb82f2c6a9c.tar.gz
cmd/gc, runtime: treat slices and strings like pointers in garbage collection
Before, a slice with cap=0 or a string with len=0 might have its base pointer pointing beyond the actual slice/string data into the next block. The collector had to ignore slices and strings with cap=0 in order to avoid misinterpreting the base pointer. Now, a slice with cap=0 or a string with len=0 still has a base pointer pointing into the actual slice/string data, no matter what. The collector can now always scan the pointer, which means strings and slices are no longer special. Fixes issue 8404. LGTM=khr, josharian R=josharian, khr, dvyukov CC=golang-codereviews https://codereview.appspot.com/112570044
Diffstat (limited to 'test/slicecap.go')
-rw-r--r--test/slicecap.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/test/slicecap.go b/test/slicecap.go
new file mode 100644
index 000000000..dceb7e2cc
--- /dev/null
+++ b/test/slicecap.go
@@ -0,0 +1,90 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+var (
+ hello = "hello"
+ bytes = []byte{1, 2, 3, 4, 5}
+ ints = []int32{1, 2, 3, 4, 5}
+
+ five = 5
+
+ ok = true
+)
+
+func notOK() {
+ if ok {
+ println("BUG:")
+ ok = false
+ }
+}
+
+func checkString(desc, s string) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&hello))
+ if p1-p2 >= 5 {
+ notOK()
+ println("string", desc, "has invalid base")
+ }
+}
+
+func checkBytes(desc string, s []byte) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&bytes))
+ if p1-p2 >= 5 {
+ println("byte slice", desc, "has invalid base")
+ }
+}
+
+func checkInts(desc string, s []int32) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&ints))
+ if p1-p2 >= 5*4 {
+ println("int slice", desc, "has invalid base")
+ }
+}
+
+func main() {
+ {
+ x := hello
+ checkString("x", x)
+ checkString("x[5:]", x[5:])
+ checkString("x[five:]", x[five:])
+ checkString("x[5:five]", x[5:five])
+ checkString("x[five:5]", x[five:5])
+ checkString("x[five:five]", x[five:five])
+ checkString("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkString("y[1:]", y[1:])
+ }
+ {
+ x := bytes
+ checkBytes("x", x)
+ checkBytes("x[5:]", x[5:])
+ checkBytes("x[five:]", x[five:])
+ checkBytes("x[5:five]", x[5:five])
+ checkBytes("x[five:5]", x[five:5])
+ checkBytes("x[five:five]", x[five:five])
+ checkBytes("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkBytes("y[1:]", y[1:])
+ }
+ {
+ x := ints
+ checkInts("x", x)
+ checkInts("x[5:]", x[5:])
+ checkInts("x[five:]", x[five:])
+ checkInts("x[5:five]", x[5:five])
+ checkInts("x[five:5]", x[five:5])
+ checkInts("x[five:five]", x[five:five])
+ checkInts("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkInts("y[1:]", y[1:])
+ }
+}