diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go index 9df85adf62..5392d809ae 100644 --- a/src/cmd/compile/internal/gc/racewalk.go +++ b/src/cmd/compile/internal/gc/racewalk.go @@ -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. diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index d392d567ca..1f2f5c68c2 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -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 diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 87623a2cc3..f5e9237b81 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -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 }