mirror of
https://github.com/golang/go
synced 2024-11-23 19:40:08 -07: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:
parent
dfaed7ff19
commit
91bbe5388d
@ -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
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user