1
0
mirror of https://github.com/golang/go synced 2024-11-26 22:31:23 -07:00
go/test/slice3.go
Russ Cox 613383c765 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 #8404.

LGTM=khr, josharian
R=josharian, khr, dvyukov
CC=golang-codereviews
https://golang.org/cl/112570044
2014-08-25 14:38:19 -04:00

161 lines
2.9 KiB
Go

// runoutput
// Copyright 2013 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.
// Test run-time behavior of 3-index slice expressions.
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
var bout *bufio.Writer
func main() {
bout = bufio.NewWriter(os.Stdout)
fmt.Fprintf(bout, "%s", programTop)
fmt.Fprintf(bout, "func main() {\n")
index := []string{
"0",
"1",
"2",
"3",
"10",
"20",
"vminus1",
"v0",
"v1",
"v2",
"v3",
"v10",
"v20",
}
parse := func(s string) (n int, isconst bool) {
if s == "vminus1" {
return -1, false
}
isconst = true
if s[0] == 'v' {
isconst = false
s = s[1:]
}
n, _ = strconv.Atoi(s)
return n, isconst
}
const Cap = 10 // cap of slice, array
for _, base := range []string{"array", "slice"} {
for _, i := range index {
iv, iconst := parse(i)
for _, j := range index {
jv, jconst := parse(j)
for _, k := range index {
kv, kconst := parse(k)
// Avoid errors that would make the program not compile.
// Those are tested by slice3err.go.
switch {
case iconst && jconst && iv > jv,
jconst && kconst && jv > kv,
iconst && kconst && iv > kv,
iconst && base == "array" && iv > Cap,
jconst && base == "array" && jv > Cap,
kconst && base == "array" && kv > Cap:
continue
}
expr := base + "[" + i + ":" + j + ":" + k + "]"
var xbase, xlen, xcap int
if iv > jv || jv > kv || kv > Cap || iv < 0 || jv < 0 || kv < 0 {
xbase, xlen, xcap = -1, -1, -1
} else {
xbase = iv
xlen = jv - iv
xcap = kv - iv
}
fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
}
}
}
}
fmt.Fprintf(bout, "\tif !ok { os.Exit(1) }\n")
fmt.Fprintf(bout, "}\n")
bout.Flush()
}
var programTop = `
package main
import (
"fmt"
"os"
"unsafe"
)
var ok = true
var (
array = new([10]byte)
slice = array[:]
vminus1 = -1
v0 = 0
v1 = 1
v2 = 2
v3 = 3
v4 = 4
v5 = 5
v10 = 10
v20 = 20
)
func notOK() {
if ok {
println("BUG:")
ok = false
}
}
func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
defer func() {
if err := recover(); err != nil {
if xbase >= 0 {
notOK()
println(desc, " unexpected panic: ", fmt.Sprint(err))
}
}
// "no panic" is checked below
}()
x := f()
arrayBase := uintptr(unsafe.Pointer(array))
raw := *(*[3]uintptr)(unsafe.Pointer(&x))
base, len, cap := raw[0] - arrayBase, raw[1], raw[2]
if xbase < 0 {
notOK()
println(desc, "=", base, len, cap, "want panic")
return
}
if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) {
notOK()
if cap == 0 {
println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap)
} else {
println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
}
}
}
`