1
0
mirror of https://github.com/golang/go synced 2024-10-01 05:18:33 -06:00

cmd/compile: sort method sets earlier

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>
This commit is contained in:
Matthew Dempsky 2018-03-15 13:14:41 -07:00
parent dfaed7ff19
commit 91bbe5388d
2 changed files with 33 additions and 27 deletions

View 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
}

View 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,18 +1848,21 @@ 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
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
@ -1866,38 +1870,41 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
}
}
*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")