cmd/compile: mark ... argument to checkptrArithmetic as not escaping
Fixes #36516
Change-Id: Ibf4f86fb3a25fa30e0cd54e2dd2e12c60ee75ddb
Reviewed-on: https://go-review.googlesource.com/c/go/+/214679
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index ef88db4..b8b954c 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1705,7 +1705,6 @@
if ddd != nil {
esc = ddd.Esc
}
-
if len(args) == 0 {
n := nodnil()
n.Type = typ
@@ -1740,6 +1739,9 @@
// then assign the remaining arguments as a slice.
if nf := params.NumFields(); nf > 0 {
if last := params.Field(nf - 1); last.IsDDD() && !n.IsDDD() {
+ // The callsite does not use a ..., but the called function is declared
+ // with a final argument that has a ... . Build the slice that we will
+ // pass as the ... argument.
tail := args[nf-1:]
slice := mkdotargslice(last.Type, tail, init, n.Right)
// Allow immediate GC.
@@ -4067,11 +4069,15 @@
n = cheapexpr(n, init)
- slice := mkdotargslice(types.NewSlice(types.Types[TUNSAFEPTR]), originals, init, nil)
- slice.Esc = EscNone
- slice.SetTransient(true)
+ ddd := nodl(n.Pos, ODDDARG, nil, nil)
+ ddd.Type = types.NewPtr(types.NewArray(types.Types[TUNSAFEPTR], int64(len(originals))))
+ ddd.Esc = EscNone
+ slice := mkdotargslice(types.NewSlice(types.Types[TUNSAFEPTR]), originals, init, ddd)
init.Append(mkcall("checkptrArithmetic", nil, init, convnop(n, types.Types[TUNSAFEPTR]), slice))
+ // TODO(khr): Mark backing store of slice as dead. This will allow us to reuse
+ // the backing store for multiple calls to checkptrArithmetic.
+
return n
}
diff --git a/test/fixedbugs/issue36516.go b/test/fixedbugs/issue36516.go
new file mode 100644
index 0000000..1472d4c
--- /dev/null
+++ b/test/fixedbugs/issue36516.go
@@ -0,0 +1,27 @@
+// +build linux,amd64
+// run -race
+
+// Copyright 2020 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 (
+ "fmt"
+ "testing"
+ "unsafe"
+)
+
+var buf [2]byte
+var x unsafe.Pointer = unsafe.Pointer(&buf[0])
+
+func main() {
+ n := testing.AllocsPerRun(1000, func() {
+ x = unsafe.Pointer(uintptr(x) + 1)
+ x = unsafe.Pointer(uintptr(x) - 1)
+ })
+ if n > 0 {
+ panic(fmt.Sprintf("too many allocations; want 0 got %f", n))
+ }
+}