mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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:
parent
2e77bc48aa
commit
aa38801788
2 changed files with 20 additions and 2 deletions
|
|
@ -1694,6 +1694,20 @@ type S13 struct {
|
||||||
S8
|
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{
|
var fieldTests = []FTest{
|
||||||
{struct{}{}, "", nil, 0},
|
{struct{}{}, "", nil, 0},
|
||||||
{struct{}{}, "Foo", nil, 0},
|
{struct{}{}, "Foo", nil, 0},
|
||||||
|
|
@ -1719,6 +1733,7 @@ var fieldTests = []FTest{
|
||||||
{S5{}, "Y", []int{2, 0, 1}, 0},
|
{S5{}, "Y", []int{2, 0, 1}, 0},
|
||||||
{S10{}, "X", nil, 0},
|
{S10{}, "X", nil, 0},
|
||||||
{S10{}, "Y", []int{2, 0, 0, 1}, 0},
|
{S10{}, "Y", []int{2, 0, 0, 1}, 0},
|
||||||
|
{S14{}, "X", nil, 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFieldByIndex(t *testing.T) {
|
func TestFieldByIndex(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -913,19 +913,22 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
|
||||||
|
|
||||||
// Queue embedded struct fields for processing with next level,
|
// Queue embedded struct fields for processing with next level,
|
||||||
// but only if we haven't seen a match yet at this level and only
|
// 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 {
|
if ok || ntyp == nil || ntyp.Kind() != Struct {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
styp := (*structType)(unsafe.Pointer(ntyp))
|
styp := (*structType)(unsafe.Pointer(ntyp))
|
||||||
if nextCount[styp] > 0 {
|
if nextCount[styp] > 0 {
|
||||||
nextCount[styp]++
|
nextCount[styp] = 2 // exact multiple doesn't matter
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if nextCount == nil {
|
if nextCount == nil {
|
||||||
nextCount = map[*structType]int{}
|
nextCount = map[*structType]int{}
|
||||||
}
|
}
|
||||||
nextCount[styp] = 1
|
nextCount[styp] = 1
|
||||||
|
if count[t] > 1 {
|
||||||
|
nextCount[styp] = 2 // exact multiple doesn't matter
|
||||||
|
}
|
||||||
var index []int
|
var index []int
|
||||||
index = append(index, scan.index...)
|
index = append(index, scan.index...)
|
||||||
index = append(index, i)
|
index = append(index, i)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue