1
0
mirror of https://github.com/golang/go synced 2024-11-19 17:14:44 -07:00

reflect: fix FieldByNameFunc

The existing algorithm did not properly propagate the type
count from one level to the next, and as a consequence it
missed collisions.

Properly propagate multiplicity (count) information to the
next level.

benchmark                old ns/op    new ns/op    delta
BenchmarkFieldByName1          182          180   -1.10%
BenchmarkFieldByName2         6273         6183   -1.43%
BenchmarkFieldByName3        49267        46784   -5.04%

Fixes #4355.

R=rsc
CC=golang-dev
https://golang.org/cl/6821094
This commit is contained in:
Robert Griesemer 2012-11-13 10:45:30 -08:00
parent 2e77bc48aa
commit aa38801788
2 changed files with 20 additions and 2 deletions

View File

@ -1694,6 +1694,20 @@ type S13 struct {
S8
}
// The X in S15.S11.S1 and S16.S11.S1 annihilate.
type S14 struct {
S15
S16
}
type S15 struct {
S11
}
type S16 struct {
S11
}
var fieldTests = []FTest{
{struct{}{}, "", nil, 0},
{struct{}{}, "Foo", nil, 0},
@ -1719,6 +1733,7 @@ var fieldTests = []FTest{
{S5{}, "Y", []int{2, 0, 1}, 0},
{S10{}, "X", nil, 0},
{S10{}, "Y", []int{2, 0, 0, 1}, 0},
{S14{}, "X", nil, 0},
}
func TestFieldByIndex(t *testing.T) {

View File

@ -913,19 +913,22 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
// Queue embedded struct fields for processing with next level,
// but only if we haven't seen a match yet at this level and only
// if the embedded types haven't alredy been queued.
// if the embedded types haven't already been queued.
if ok || ntyp == nil || ntyp.Kind() != Struct {
continue
}
styp := (*structType)(unsafe.Pointer(ntyp))
if nextCount[styp] > 0 {
nextCount[styp]++
nextCount[styp] = 2 // exact multiple doesn't matter
continue
}
if nextCount == nil {
nextCount = map[*structType]int{}
}
nextCount[styp] = 1
if count[t] > 1 {
nextCount[styp] = 2 // exact multiple doesn't matter
}
var index []int
index = append(index, scan.index...)
index = append(index, i)