mirror of
https://github.com/golang/go
synced 2024-11-18 23:05:06 -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
|
return ms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1628,6 +1628,7 @@ func expandmeth(t *types.Type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ms = append(ms, t.Methods().Slice()...)
|
ms = append(ms, t.Methods().Slice()...)
|
||||||
|
sort.Sort(methcmp(ms))
|
||||||
t.AllMethods().Set(ms)
|
t.AllMethods().Set(ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1847,18 +1848,21 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this is too slow,
|
|
||||||
// could sort these first
|
|
||||||
// and then do one loop.
|
|
||||||
|
|
||||||
if t.IsInterface() {
|
if t.IsInterface() {
|
||||||
Outer:
|
i := 0
|
||||||
|
tms := t.Fields().Slice()
|
||||||
for _, im := range iface.Fields().Slice() {
|
for _, im := range iface.Fields().Slice() {
|
||||||
for _, tm := range t.Fields().Slice() {
|
for i < len(tms) && tms[i].Sym != im.Sym {
|
||||||
if tm.Sym == im.Sym {
|
i++
|
||||||
if eqtype(tm.Type, im.Type) {
|
|
||||||
continue Outer
|
|
||||||
}
|
}
|
||||||
|
if i == len(tms) {
|
||||||
|
*m = im
|
||||||
|
*samename = nil
|
||||||
|
*ptr = 0
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tm := tms[i]
|
||||||
|
if !eqtype(tm.Type, im.Type) {
|
||||||
*m = im
|
*m = im
|
||||||
*samename = tm
|
*samename = tm
|
||||||
*ptr = 0
|
*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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
t = methtype(t)
|
t = methtype(t)
|
||||||
|
var tms []*types.Field
|
||||||
if t != nil {
|
if t != nil {
|
||||||
expandmeth(t)
|
expandmeth(t)
|
||||||
|
tms = t.AllMethods().Slice()
|
||||||
}
|
}
|
||||||
|
i := 0
|
||||||
for _, im := range iface.Fields().Slice() {
|
for _, im := range iface.Fields().Slice() {
|
||||||
if im.Broke() {
|
if im.Broke() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tm, followptr := ifacelookdot(im.Sym, t, false)
|
for i < len(tms) && tms[i].Sym != im.Sym {
|
||||||
if tm == nil || tm.Nointerface() || !eqtype(tm.Type, im.Type) {
|
i++
|
||||||
if tm == nil {
|
|
||||||
tm, followptr = ifacelookdot(im.Sym, t, true)
|
|
||||||
}
|
}
|
||||||
|
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
|
*m = im
|
||||||
*samename = tm
|
*samename = tm
|
||||||
*ptr = 0
|
*ptr = 0
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
followptr := tm.Embedded == 2
|
||||||
|
|
||||||
// if pointer receiver in method,
|
// if pointer receiver in method,
|
||||||
// the method does not exist for value types.
|
// the method does not exist for value types.
|
||||||
rcvr := tm.Type.Recv().Type
|
rcvr := tm.Type.Recv().Type
|
||||||
|
|
||||||
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
|
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
|
||||||
if false && Debug['r'] != 0 {
|
if false && Debug['r'] != 0 {
|
||||||
yyerror("interface pointer mismatch")
|
yyerror("interface pointer mismatch")
|
||||||
|
Loading…
Reference in New Issue
Block a user