mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/compile, cmd/link: remove dead methods if type is not used in interface
Currently, a method of a reachable type is live if it matches a method of a reachable interface. In fact, we only need to retain the method if the type is actually converted to an interface. If the type is never converted to an interface, there is no way to call the method through an interface method call (but the type descriptor could still be used, e.g. in calling runtime.newobject). A type can be used in an interface in two ways: - directly converted to interface. (Any interface counts, as it is possible to convert one interface to another.) - obtained by reflection from a related type (e.g. obtaining an interface of T from []T). For the former, we let the compiler emit a marker on the type descriptor symbol when it is converted to an interface. In the linker, we only need to check methods of marked types. For the latter, when the linker visits a marked type, it needs to visit all its "child" types as marked (i.e. potentially could be converted to interface). This reduces binary size: cmd/compile 18792016 18706096 (-0.5%) cmd/go 14120572 13398948 (-5.1%) Change-Id: I4465c7eeabf575f4dc84017214c610fa05ae31fd Reviewed-on: https://go-review.googlesource.com/c/go/+/237298 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
parent
3187b05b87
commit
95848fc5c6
11 changed files with 142 additions and 15 deletions
|
|
@ -244,7 +244,8 @@ type Loader struct {
|
|||
attrReachable Bitmap // reachable symbols, indexed by global index
|
||||
attrOnList Bitmap // "on list" symbols, indexed by global index
|
||||
attrLocal Bitmap // "local" symbols, indexed by global index
|
||||
attrNotInSymbolTable Bitmap // "not in symtab" symbols, indexed by glob idx
|
||||
attrNotInSymbolTable Bitmap // "not in symtab" symbols, indexed by global idx
|
||||
attrUsedInIface Bitmap // "used in interface" symbols, indexed by global idx
|
||||
attrVisibilityHidden Bitmap // hidden symbols, indexed by ext sym index
|
||||
attrDuplicateOK Bitmap // dupOK symbols, indexed by ext sym index
|
||||
attrShared Bitmap // shared symbols, indexed by ext sym index
|
||||
|
|
@ -768,6 +769,20 @@ func (l *Loader) SetAttrLocal(i Sym, v bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// AttrUsedInIface returns true for a type symbol that is used in
|
||||
// an interface.
|
||||
func (l *Loader) AttrUsedInIface(i Sym) bool {
|
||||
return l.attrUsedInIface.Has(i)
|
||||
}
|
||||
|
||||
func (l *Loader) SetAttrUsedInIface(i Sym, v bool) {
|
||||
if v {
|
||||
l.attrUsedInIface.Set(i)
|
||||
} else {
|
||||
l.attrUsedInIface.Unset(i)
|
||||
}
|
||||
}
|
||||
|
||||
// SymAddr checks that a symbol is reachable, and returns its value.
|
||||
func (l *Loader) SymAddr(i Sym) int64 {
|
||||
if !l.AttrReachable(i) {
|
||||
|
|
@ -1665,6 +1680,7 @@ func (l *Loader) growAttrBitmaps(reqLen int) {
|
|||
l.attrOnList = growBitmap(reqLen, l.attrOnList)
|
||||
l.attrLocal = growBitmap(reqLen, l.attrLocal)
|
||||
l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
|
||||
l.attrUsedInIface = growBitmap(reqLen, l.attrUsedInIface)
|
||||
}
|
||||
l.growExtAttrBitmaps()
|
||||
}
|
||||
|
|
@ -1983,6 +1999,9 @@ func (l *Loader) preloadSyms(r *oReader, kind int) {
|
|||
if osym.Local() {
|
||||
l.SetAttrLocal(gi, true)
|
||||
}
|
||||
if osym.UsedInIface() {
|
||||
l.SetAttrUsedInIface(gi, true)
|
||||
}
|
||||
if strings.HasPrefix(name, "go.itablink.") {
|
||||
l.itablink[gi] = struct{}{}
|
||||
}
|
||||
|
|
@ -2025,6 +2044,9 @@ func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
|
|||
if osym.Local() {
|
||||
l.SetAttrLocal(gi, true)
|
||||
}
|
||||
if osym.UsedInIface() {
|
||||
l.SetAttrUsedInIface(gi, true)
|
||||
}
|
||||
l.preprocess(arch, gi, name)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue