]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: in escape analysis, use element type for OIND of slice
authorCherry Zhang <cherryyz@google.com>
Tue, 17 Apr 2018 20:28:13 +0000 (16:28 -0400)
committerCherry Zhang <cherryyz@google.com>
Wed, 18 Apr 2018 02:59:37 +0000 (02:59 +0000)
The escape analysis models the flow of "content" of X with a
level of "indirection" (OIND node) of X. This content can be
pointer dereference, or slice/string element. For the latter
case, the type of the OIND node should be the element type of
the slice/string. This CL fixes this. In particular, this
matters when the element type is pointerless, where the data
flow should not cause any escape.

Fixes #15730.

Change-Id: Iba9f92898681625e7e3ddef76ae65d7cd61c41e0
Reviewed-on: https://go-review.googlesource.com/107597
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/gc/esc.go
test/escape5.go

index 64ac29e7640971a7c7045a7ac7e25c1a0680eb9e..dee315d6f0fad10e479db0597363c36f1b05af77 100644 (file)
@@ -1405,11 +1405,13 @@ func (e *EscState) addDereference(n *Node) *Node {
        e.nodeEscState(ind).Loopdepth = e.nodeEscState(n).Loopdepth
        ind.Pos = n.Pos
        t := n.Type
-       if t.IsKind(types.Tptr) {
+       if t.IsKind(types.Tptr) || t.IsSlice() {
                // This should model our own sloppy use of OIND to encode
-               // decreasing levels of indirection; i.e., "indirecting" an array
-               // might yield the type of an element. To be enhanced...
+               // decreasing levels of indirection; i.e., "indirecting" a slice
+               // yields the type of an element.
                t = t.Elem()
+       } else if t.IsString() {
+               t = types.Types[TUINT8]
        }
        ind.Type = t
        return ind
index d02f735f8fc1faa3eb17af59c2580978028a7b88..03283a37f8470ac283061ee98459641c7c8ee979 100644 (file)
@@ -194,3 +194,37 @@ func (t *T24730) g() { // ERROR "t does not escape"
                *z = 2
        }
 }
+
+// Issue 15730: copy causes unnecessary escape
+
+var sink []byte
+var sink2 []int
+var sink3 []*int
+
+func f15730a(args ...interface{}) { // ERROR "args does not escape"
+       for _, arg := range args {
+               switch a := arg.(type) {
+               case string:
+                       copy(sink, a)
+               }
+       }
+}
+
+func f15730b(args ...interface{}) { // ERROR "args does not escape"
+       for _, arg := range args {
+               switch a := arg.(type) {
+               case []int:
+                       copy(sink2, a)
+               }
+       }
+}
+
+func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
+       for _, arg := range args {
+               switch a := arg.(type) {
+               case []*int:
+                       // copy pointerful data should cause escape
+                       copy(sink3, a)
+               }
+       }
+}