]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: optimize Named type method lookup
authorRobert Griesemer <gri@golang.org>
Wed, 7 Feb 2024 05:57:06 +0000 (21:57 -0800)
committerRobert Griesemer <gri@google.com>
Wed, 7 Feb 2024 17:03:59 +0000 (17:03 +0000)
Because methods associated with named types are in the
same package as the type, when looking up a method we
don't need to check the package repeatedly.

Rename the global lookupMethod function to methodIndex,
to match the corresponding fieldIndex function (cleanup).

Implement Named.methodIndex, optimized for method lookup
on named types (optimization).

Adjust call sites.

Change-Id: Ifa05306126773262b1af3ce73365b5742b470eb6
Reviewed-on: https://go-review.googlesource.com/c/go/+/562297
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>

src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/typeset.go
src/go/types/lookup.go
src/go/types/named.go
src/go/types/typeset.go

index 15e80a0b1bb3a279e7c04ba74eaa93b31bdfb3c8..5aa8091a5c2bd617ab6274de4204f4b40f9894ff 100644 (file)
@@ -590,9 +590,9 @@ func fieldIndex(fields []*Var, pkg *Package, name string, foldCase bool) int {
        return -1
 }
 
-// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
+// methodIndex returns the index of and method with matching package and name, or (-1, nil).
 // See Object.sameId for the meaning of foldCase.
-func lookupMethod(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
+func methodIndex(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
        if name != "_" {
                for i, m := range methods {
                        if m.sameId(pkg, name, foldCase) {
index 893247de35b671e063990fb70586ca9db7447d01..57caef123f97281df8b93224a6c31addff108f35 100644 (file)
@@ -6,6 +6,7 @@ package types2
 
 import (
        "cmd/compile/internal/syntax"
+       "strings"
        "sync"
        "sync/atomic"
 )
@@ -444,15 +445,40 @@ func (t *Named) SetUnderlying(underlying Type) {
 }
 
 // AddMethod adds method m unless it is already in the method list.
-// t must not have type arguments.
+// The method must be in the same package as t, and t must not have
+// type arguments.
 func (t *Named) AddMethod(m *Func) {
+       assert(samePkg(t.obj.pkg, m.pkg))
        assert(t.inst == nil)
        t.resolve()
-       if i, _ := lookupMethod(t.methods, m.pkg, m.name, false); i < 0 {
+       if t.methodIndex(m.name, false) < 0 {
                t.methods = append(t.methods, m)
        }
 }
 
+// methodIndex returns the index of the method with the given name.
+// If foldCase is set, capitalization in the name is ignored.
+// The result is negative if no such method exists.
+func (t *Named) methodIndex(name string, foldCase bool) int {
+       if name == "_" {
+               return -1
+       }
+       if foldCase {
+               for i, m := range t.methods {
+                       if strings.EqualFold(m.name, name) {
+                               return i
+                       }
+               }
+       } else {
+               for i, m := range t.methods {
+                       if m.name == name {
+                               return i
+                       }
+               }
+       }
+       return -1
+}
+
 // TODO(gri) Investigate if Unalias can be moved to where underlying is set.
 func (t *Named) Underlying() Type { return Unalias(t.resolve().underlying) }
 func (t *Named) String() string   { return TypeString(t, nil) }
@@ -553,15 +579,16 @@ loop:
 
 func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
        n.resolve()
-       // If n is an instance, we may not have yet instantiated all of its methods.
-       // Look up the method index in orig, and only instantiate method at the
-       // matching index (if any).
-       i, _ := lookupMethod(n.Origin().methods, pkg, name, foldCase)
-       if i < 0 {
-               return -1, nil
-       }
-       // For instances, m.Method(i) will be different from the orig method.
-       return i, n.Method(i)
+       if samePkg(n.obj.pkg, pkg) || isExported(name) || foldCase {
+               // If n is an instance, we may not have yet instantiated all of its methods.
+               // Look up the method index in orig, and only instantiate method at the
+               // matching index (if any).
+               if i := n.Origin().methodIndex(name, foldCase); i >= 0 {
+                       // For instances, m.Method(i) will be different from the orig method.
+                       return i, n.Method(i)
+               }
+       }
+       return -1, nil
 }
 
 // context returns the type-checker context.
index a6ccfdb80cc727744c92c44d4cd5f92c6fcdefa4..bf07162a2166fa8121a843e0f63b1fee002a792f 100644 (file)
@@ -57,7 +57,7 @@ func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
 
 // LookupMethod returns the index of and method with matching package and name, or (-1, nil).
 func (s *_TypeSet) LookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
-       return lookupMethod(s.methods, pkg, name, foldCase)
+       return methodIndex(s.methods, pkg, name, foldCase)
 }
 
 func (s *_TypeSet) String() string {
index 82425f64a8743cc0eb8605195bca7973385d5312..436a7afbaad5a99092cdea9ffb946f2f2a0e9c91 100644 (file)
@@ -592,9 +592,9 @@ func fieldIndex(fields []*Var, pkg *Package, name string, foldCase bool) int {
        return -1
 }
 
-// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
+// methodIndex returns the index of and method with matching package and name, or (-1, nil).
 // See Object.sameId for the meaning of foldCase.
-func lookupMethod(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
+func methodIndex(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
        if name != "_" {
                for i, m := range methods {
                        if m.sameId(pkg, name, foldCase) {
index 21c0de255dedba8db35edd79192f509d90ec6ee4..e053fed76ba368209a61e42b8af71fc6aa450327 100644 (file)
@@ -8,6 +8,7 @@ package types
 
 import (
        "go/token"
+       "strings"
        "sync"
        "sync/atomic"
 )
@@ -446,15 +447,40 @@ func (t *Named) SetUnderlying(underlying Type) {
 }
 
 // AddMethod adds method m unless it is already in the method list.
-// t must not have type arguments.
+// The method must be in the same package as t, and t must not have
+// type arguments.
 func (t *Named) AddMethod(m *Func) {
+       assert(samePkg(t.obj.pkg, m.pkg))
        assert(t.inst == nil)
        t.resolve()
-       if i, _ := lookupMethod(t.methods, m.pkg, m.name, false); i < 0 {
+       if t.methodIndex(m.name, false) < 0 {
                t.methods = append(t.methods, m)
        }
 }
 
+// methodIndex returns the index of the method with the given name.
+// If foldCase is set, capitalization in the name is ignored.
+// The result is negative if no such method exists.
+func (t *Named) methodIndex(name string, foldCase bool) int {
+       if name == "_" {
+               return -1
+       }
+       if foldCase {
+               for i, m := range t.methods {
+                       if strings.EqualFold(m.name, name) {
+                               return i
+                       }
+               }
+       } else {
+               for i, m := range t.methods {
+                       if m.name == name {
+                               return i
+                       }
+               }
+       }
+       return -1
+}
+
 // TODO(gri) Investigate if Unalias can be moved to where underlying is set.
 func (t *Named) Underlying() Type { return Unalias(t.resolve().underlying) }
 func (t *Named) String() string   { return TypeString(t, nil) }
@@ -555,15 +581,16 @@ loop:
 
 func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
        n.resolve()
-       // If n is an instance, we may not have yet instantiated all of its methods.
-       // Look up the method index in orig, and only instantiate method at the
-       // matching index (if any).
-       i, _ := lookupMethod(n.Origin().methods, pkg, name, foldCase)
-       if i < 0 {
-               return -1, nil
-       }
-       // For instances, m.Method(i) will be different from the orig method.
-       return i, n.Method(i)
+       if samePkg(n.obj.pkg, pkg) || isExported(name) || foldCase {
+               // If n is an instance, we may not have yet instantiated all of its methods.
+               // Look up the method index in orig, and only instantiate method at the
+               // matching index (if any).
+               if i := n.Origin().methodIndex(name, foldCase); i >= 0 {
+                       // For instances, m.Method(i) will be different from the orig method.
+                       return i, n.Method(i)
+               }
+       }
+       return -1, nil
 }
 
 // context returns the type-checker context.
index d164749996e22304d318536d10affac7a1fcd260..4e3865ddc4ceed7fa2c915df53c1799a377b5413 100644 (file)
@@ -57,7 +57,7 @@ func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
 
 // LookupMethod returns the index of and method with matching package and name, or (-1, nil).
 func (s *_TypeSet) LookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
-       return lookupMethod(s.methods, pkg, name, foldCase)
+       return methodIndex(s.methods, pkg, name, foldCase)
 }
 
 func (s *_TypeSet) String() string {