Commit bbfae469 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: handle blank struct fields in NumComponents

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: 's avatarMatthew Dempsky <mdempsky@google.com>
parent d8b417e0
......@@ -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.
......
......@@ -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
......
......@@ -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
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment