]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: handle blank struct fields in NumComponents
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 30 Mar 2018 19:25:02 +0000 (12:25 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Sat, 7 Apr 2018 21:01:07 +0000 (21:01 +0000)
NumComponents is used by racewalk to decide whether reads and writes
might occur to subobjects of an address. For that purpose,
blank fields matter.

It is also used to decide whether to inline == and != for a type.
For that purpose, blank fields may be ignored.

Add a parameter to NumComponents to support this distinction.
While we're here, document NumComponents, as requested in CL 59334.

Change-Id: I8c2021b172edadd6184848a32a74774dde1805c8
Reviewed-on: https://go-review.googlesource.com/103755
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/racewalk.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/types/type.go

index 9df85adf62654d479f463be47320dd2332a957bf..5392d809ae4e0180e97783f1db45d6db9729b104 100644 (file)
@@ -461,7 +461,7 @@ func callinstr(np **Node, init *Nodes, wr, skip bool) {
                                name = "msanwrite"
                        }
                        f = mkcall(name, nil, init, uintptraddr(n), nodintconst(w))
-               } else if flag_race && t.NumComponents() > 1 {
+               } else if flag_race && t.NumComponents(types.CountBlankFields) > 1 {
                        // for composite objects we have to write every address
                        // because a write might happen to any subobject.
                        // composites with only one element don't have subobjects, though.
index d392d567cafbc5b9333a5e87fbd411eab2ddd7f2..1f2f5c68c237143992033700c3c1274a37829d23 100644 (file)
@@ -3298,7 +3298,7 @@ func walkcompare(n *Node, init *Nodes) *Node {
                // We can compare several elements at once with 2/4/8 byte integer compares
                inline = t.NumElem() <= 1 || (issimple[t.Elem().Etype] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize))
        case TSTRUCT:
-               inline = t.NumComponents() <= 4
+               inline = t.NumComponents(types.IgnoreBlankFields) <= 4
        }
 
        cmpl := n.Left
index 87623a2cc30fe11fbfbe5f5c597e7616b771d5bd..f5e9237b81a30b53b08489d5cef980086cc3d1a0 100644 (file)
@@ -1325,7 +1325,20 @@ func (t *Type) SetNumElem(n int64) {
        at.Bound = n
 }
 
-func (t *Type) NumComponents() int64 {
+type componentsIncludeBlankFields bool
+
+const (
+       IgnoreBlankFields componentsIncludeBlankFields = false
+       CountBlankFields  componentsIncludeBlankFields = true
+)
+
+// NumComponents returns the number of primitive elements that compose t.
+// Struct and array types are flattened for the purpose of counting.
+// All other types (including string, slice, and interface types) count as one element.
+// If countBlank is IgnoreBlankFields, then blank struct fields
+// (and their comprised elements) are excluded from the count.
+// struct { x, y [3]int } has six components; [10]struct{ x, y string } has twenty.
+func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
        switch t.Etype {
        case TSTRUCT:
                if t.IsFuncArgStruct() {
@@ -1333,11 +1346,14 @@ func (t *Type) NumComponents() int64 {
                }
                var n int64
                for _, f := range t.FieldSlice() {
-                       n += f.Type.NumComponents()
+                       if countBlank == IgnoreBlankFields && f.Sym.IsBlank() {
+                               continue
+                       }
+                       n += f.Type.NumComponents(countBlank)
                }
                return n
        case TARRAY:
-               return t.NumElem() * t.Elem().NumComponents()
+               return t.NumElem() * t.Elem().NumComponents(countBlank)
        }
        return 1
 }