]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: sort method sets earlier
authorMatthew Dempsky <mdempsky@google.com>
Thu, 15 Mar 2018 20:14:41 +0000 (13:14 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 15 Mar 2018 21:53:01 +0000 (21:53 +0000)
By sorting method sets earlier, we can change the interface
satisfaction problem from taking O(NM) time to O(N+M). This is the
same algorithm already used by runtime and reflect for dynamic
interface satisfaction testing.

For #22075.

Change-Id: I3d889f0227f37704535739bbde11f5107b4eea17
Reviewed-on: https://go-review.googlesource.com/100845
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/subr.go

index 1535991a7851e07e19b8134f68f17f622f470c01..eeb74c6236a92323669070471371813270885f35 100644 (file)
@@ -454,7 +454,6 @@ func methods(t *types.Type) []*Sig {
                }
        }
 
-       obj.SortSlice(ms, func(i, j int) bool { return siglt(ms[i], ms[j]) })
        return ms
 }
 
index 86d5539ca2e0b925117e9008b357da8fb4154602..91e99fc2d6611767ce39b376c155476c0721afa5 100644 (file)
@@ -1628,6 +1628,7 @@ func expandmeth(t *types.Type) {
        }
 
        ms = append(ms, t.Methods().Slice()...)
+       sort.Sort(methcmp(ms))
        t.AllMethods().Set(ms)
 }
 
@@ -1847,57 +1848,63 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
                return false
        }
 
-       // if this is too slow,
-       // could sort these first
-       // and then do one loop.
-
        if t.IsInterface() {
-       Outer:
+               i := 0
+               tms := t.Fields().Slice()
                for _, im := range iface.Fields().Slice() {
-                       for _, tm := range t.Fields().Slice() {
-                               if tm.Sym == im.Sym {
-                                       if eqtype(tm.Type, im.Type) {
-                                               continue Outer
-                                       }
-                                       *m = im
-                                       *samename = tm
-                                       *ptr = 0
-                                       return false
-                               }
+                       for i < len(tms) && tms[i].Sym != im.Sym {
+                               i++
+                       }
+                       if i == len(tms) {
+                               *m = im
+                               *samename = nil
+                               *ptr = 0
+                               return false
+                       }
+                       tm := tms[i]
+                       if !eqtype(tm.Type, im.Type) {
+                               *m = im
+                               *samename = tm
+                               *ptr = 0
+                               return false
                        }
-
-                       *m = im
-                       *samename = nil
-                       *ptr = 0
-                       return false
                }
 
                return true
        }
 
        t = methtype(t)
+       var tms []*types.Field
        if t != nil {
                expandmeth(t)
+               tms = t.AllMethods().Slice()
        }
+       i := 0
        for _, im := range iface.Fields().Slice() {
                if im.Broke() {
                        continue
                }
-               tm, followptr := ifacelookdot(im.Sym, t, false)
-               if tm == nil || tm.Nointerface() || !eqtype(tm.Type, im.Type) {
-                       if tm == nil {
-                               tm, followptr = ifacelookdot(im.Sym, t, true)
-                       }
+               for i < len(tms) && tms[i].Sym != im.Sym {
+                       i++
+               }
+               if i == len(tms) {
+                       *m = im
+                       *samename, _ = ifacelookdot(im.Sym, t, true)
+                       *ptr = 0
+                       return false
+               }
+               tm := tms[i]
+               if tm.Nointerface() || !eqtype(tm.Type, im.Type) {
                        *m = im
                        *samename = tm
                        *ptr = 0
                        return false
                }
+               followptr := tm.Embedded == 2
 
                // if pointer receiver in method,
                // the method does not exist for value types.
                rcvr := tm.Type.Recv().Type
-
                if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
                        if false && Debug['r'] != 0 {
                                yyerror("interface pointer mismatch")