mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
934c359964
func f(x, y, z *int) { a := []*int{x,y,z} ... } We used to use: var tmp [3]*int a := tmp[:] a[0] = x a[1] = y a[2] = z Now we do: var tmp [3]*int tmp[0] = x tmp[1] = y tmp[2] = z a := tmp[:] Doesn't sound like a big deal, but the compiler has trouble eliminating write barriers when using the former method because it doesn't know that the slice points to the stack. In the latter method, the compiler knows the array is on the stack and as a result doesn't emit any write barriers. This turns out to be extremely common when building ... args, like for calls fmt.Printf. Makes go binaries ~1% smaller. Doesn't have a measurable effect on the go1 fmt benchmarks, unfortunately. Fixes #14263 Update #6853 Change-Id: I9074a2788ec9e561a75f3b71c119b69f304d6ba2 Reviewed-on: https://go-review.googlesource.com/22395 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
198 lines
3.7 KiB
Go
198 lines
3.7 KiB
Go
// errorcheck -0 -l -d=wb
|
|
|
|
// Copyright 2015 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 where write barriers are and are not emitted.
|
|
|
|
package p
|
|
|
|
import "unsafe"
|
|
|
|
func f(x **byte, y *byte) {
|
|
*x = y // ERROR "write barrier"
|
|
|
|
z := y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f1(x *[]byte, y []byte) {
|
|
*x = y // ERROR "write barrier"
|
|
|
|
z := y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f1a(x *[]byte, y *[]byte) {
|
|
*x = *y // ERROR "write barrier"
|
|
|
|
z := *y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f2(x *interface{}, y interface{}) {
|
|
*x = y // ERROR "write barrier"
|
|
|
|
z := y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f2a(x *interface{}, y *interface{}) {
|
|
*x = *y // ERROR "write barrier"
|
|
|
|
z := y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f3(x *string, y string) {
|
|
*x = y // ERROR "write barrier"
|
|
|
|
z := y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f3a(x *string, y *string) {
|
|
*x = *y // ERROR "write barrier"
|
|
|
|
z := *y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f4(x *[2]string, y [2]string) {
|
|
*x = y // ERROR "write barrier"
|
|
|
|
z := y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
func f4a(x *[2]string, y *[2]string) {
|
|
*x = *y // ERROR "write barrier"
|
|
|
|
z := *y // no barrier
|
|
*x = z // ERROR "write barrier"
|
|
}
|
|
|
|
type T struct {
|
|
X *int
|
|
Y int
|
|
M map[int]int
|
|
}
|
|
|
|
func f5(t, u *T) {
|
|
t.X = &u.Y // ERROR "write barrier"
|
|
}
|
|
|
|
func f6(t *T) {
|
|
t.M = map[int]int{1: 2} // ERROR "write barrier"
|
|
}
|
|
|
|
func f7(x, y *int) []*int {
|
|
var z [3]*int
|
|
i := 0
|
|
z[i] = x // ERROR "write barrier"
|
|
i++
|
|
z[i] = y // ERROR "write barrier"
|
|
i++
|
|
return z[:i]
|
|
}
|
|
|
|
func f9(x *interface{}, v *byte) {
|
|
*x = v // ERROR "write barrier"
|
|
}
|
|
|
|
func f10(x *byte, f func(interface{})) {
|
|
f(x)
|
|
}
|
|
|
|
func f11(x *unsafe.Pointer, y unsafe.Pointer) {
|
|
*x = unsafe.Pointer(uintptr(y) + 1) // ERROR "write barrier"
|
|
}
|
|
|
|
func f12(x []*int, y *int) []*int {
|
|
// write barrier for storing y in x's underlying array
|
|
x = append(x, y) // ERROR "write barrier"
|
|
return x
|
|
}
|
|
|
|
func f12a(x []int, y int) []int {
|
|
// y not a pointer, so no write barriers in this function
|
|
x = append(x, y)
|
|
return x
|
|
}
|
|
|
|
func f13(x []int, y *[]int) {
|
|
*y = append(x, 1) // ERROR "write barrier"
|
|
}
|
|
|
|
func f14(y *[]int) {
|
|
*y = append(*y, 1) // ERROR "write barrier"
|
|
}
|
|
|
|
type T1 struct {
|
|
X *int
|
|
}
|
|
|
|
func f15(x []T1, y T1) []T1 {
|
|
return append(x, y) // ERROR "write barrier"
|
|
}
|
|
|
|
type T8 struct {
|
|
X [8]*int
|
|
}
|
|
|
|
func f16(x []T8, y T8) []T8 {
|
|
return append(x, y) // ERROR "write barrier"
|
|
}
|
|
|
|
func t1(i interface{}) **int {
|
|
// From issue 14306, make sure we have write barriers in a type switch
|
|
// where the assigned variable escapes.
|
|
switch x := i.(type) { // ERROR "write barrier"
|
|
case *int:
|
|
return &x
|
|
}
|
|
switch y := i.(type) { // no write barrier here
|
|
case **int:
|
|
return y
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type T17 struct {
|
|
f func(*T17)
|
|
}
|
|
|
|
func f17(x *T17) {
|
|
// See golang.org/issue/13901
|
|
x.f = f17 // no barrier
|
|
x.f = func(y *T17) { *y = *x } // ERROR "write barrier"
|
|
}
|
|
|
|
type T18 struct {
|
|
a []int
|
|
s string
|
|
}
|
|
|
|
func f18(p *T18, x *[]int) {
|
|
p.a = p.a[:5] // no barrier
|
|
*x = (*x)[0:5] // no barrier
|
|
p.a = p.a[3:5] // ERROR "write barrier"
|
|
p.a = p.a[1:2:3] // ERROR "write barrier"
|
|
p.s = p.s[8:9] // ERROR "write barrier"
|
|
*x = (*x)[3:5] // ERROR "write barrier"
|
|
}
|
|
|
|
func f19(x, y *int, i int) int {
|
|
// Constructing a temporary slice on the stack should not
|
|
// require any write barriers. See issue 14263.
|
|
a := []*int{x, y} // no barrier
|
|
return *a[i]
|
|
}
|
|
|
|
func f20(x, y *int, i int) []*int {
|
|
// ... but if that temporary slice escapes, then the
|
|
// write barriers are necessary.
|
|
a := []*int{x, y} // ERROR "write barrier"
|
|
return a
|
|
}
|