mirror of
https://github.com/golang/go
synced 2024-11-18 14:54:40 -07:00
cmd/compile/internal/noder: optimize itabs section of runtime dicts
Currently, the itabs section for runtime dictionaries includes its own redundant *runtime._type pointers for typ and iface, which were sometimes necessary. This simplified the initial implementation, but is a little wasteful of space when the same type or interface appeared across multiple (typ, iface) pairs. This CL instead reuses the pointers from the rtypes section. Change-Id: I48448515c319c0403c1a8e7706794d443176f0a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/427754 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
3e11e61f3c
commit
9fc09d2ffb
@ -1386,27 +1386,18 @@ func (pr *pkgReader) dictNameOf(dict *readerDict) *ir.Name {
|
||||
reflectdata.MarkTypeUsedInInterface(typ, lsym)
|
||||
}
|
||||
|
||||
// For each (typ, iface) pair, we write *runtime._type pointers
|
||||
// for typ and iface, as well as the *runtime.itab pointer for the
|
||||
// pair. This is wasteful, but it simplifies worrying about tricky
|
||||
// cases like instantiating type parameters with interface types.
|
||||
//
|
||||
// TODO(mdempsky): Add the needed *runtime._type pointers into the
|
||||
// rtypes section above instead, and omit itabs entries when we
|
||||
// statically know it won't be needed.
|
||||
// For each (typ, iface) pair, we write the *runtime.itab pointer
|
||||
// for the pair. For pairs that don't actually require an itab
|
||||
// (i.e., typ is an interface, or iface is an empty interface), we
|
||||
// write a nil pointer instead. This is wasteful, but rare in
|
||||
// practice (e.g., instantiating a type parameter with an interface
|
||||
// type).
|
||||
assertOffset("itabs", dict.itabsOffset())
|
||||
for _, info := range dict.itabs {
|
||||
typ := pr.typIdx(info.typ, dict, true)
|
||||
iface := pr.typIdx(info.iface, dict, true)
|
||||
|
||||
if !iface.IsInterface() {
|
||||
ot += 3 * types.PtrSize
|
||||
continue
|
||||
}
|
||||
|
||||
ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(typ), 0)
|
||||
ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(iface), 0)
|
||||
if !typ.IsInterface() && !iface.IsEmptyInterface() {
|
||||
if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
|
||||
ot = objw.SymPtr(lsym, ot, reflectdata.ITabLsym(typ, iface), 0)
|
||||
} else {
|
||||
ot += types.PtrSize
|
||||
@ -1452,7 +1443,7 @@ func (dict *readerDict) itabsOffset() int {
|
||||
// numWords returns the total number of words that comprise dict's
|
||||
// runtime dictionary variable.
|
||||
func (dict *readerDict) numWords() int64 {
|
||||
return int64(dict.itabsOffset() + 3*len(dict.itabs))
|
||||
return int64(dict.itabsOffset() + len(dict.itabs))
|
||||
}
|
||||
|
||||
// varType returns the type of dict's runtime dictionary variable.
|
||||
@ -3152,28 +3143,35 @@ func (r *reader) varDictIndex(name *ir.Name) {
|
||||
}
|
||||
}
|
||||
|
||||
// itab returns a (typ, iface) pair of types.
|
||||
//
|
||||
// typRType and ifaceRType are expressions that evaluate to the
|
||||
// *runtime._type for typ and iface, respectively.
|
||||
//
|
||||
// If typ is a concrete type and iface is a non-empty interface type,
|
||||
// then itab is an expression that evaluates to the *runtime.itab for
|
||||
// the pair. Otherwise, itab is nil.
|
||||
func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
|
||||
if r.Bool() { // derived types
|
||||
idx := r.Len()
|
||||
info := r.dict.itabs[idx]
|
||||
typ = r.p.typIdx(info.typ, r.dict, true)
|
||||
typRType = r.rttiWord(pos, r.dict.itabsOffset()+3*idx)
|
||||
iface = r.p.typIdx(info.iface, r.dict, true)
|
||||
ifaceRType = r.rttiWord(pos, r.dict.itabsOffset()+3*idx+1)
|
||||
itab = r.rttiWord(pos, r.dict.itabsOffset()+3*idx+2)
|
||||
return
|
||||
typ, typRType = r.rtype0(pos)
|
||||
iface, ifaceRType = r.rtype0(pos)
|
||||
|
||||
idx := -1
|
||||
if r.Bool() {
|
||||
idx = r.Len()
|
||||
}
|
||||
|
||||
typ = r.typ()
|
||||
iface = r.typ()
|
||||
if iface.IsInterface() {
|
||||
typRType = reflectdata.TypePtrAt(pos, typ)
|
||||
ifaceRType = reflectdata.TypePtrAt(pos, iface)
|
||||
if !typ.IsInterface() && !iface.IsEmptyInterface() {
|
||||
if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
|
||||
if idx >= 0 {
|
||||
itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
|
||||
} else {
|
||||
base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
|
||||
base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
|
||||
|
||||
lsym := reflectdata.ITabLsym(typ, iface)
|
||||
itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -3215,9 +3213,7 @@ func (r *reader) exprType() ir.Node {
|
||||
|
||||
if r.Bool() {
|
||||
typ, rtype, _, _, itab = r.itab(pos)
|
||||
if typ.IsInterface() {
|
||||
itab = nil
|
||||
} else {
|
||||
if !typ.IsInterface() {
|
||||
rtype = nil // TODO(mdempsky): Leave set?
|
||||
}
|
||||
} else {
|
||||
|
@ -2183,9 +2183,13 @@ func (w *writer) exprs(exprs []syntax.Expr) {
|
||||
func (w *writer) rtype(typ types2.Type) {
|
||||
typ = types2.Default(typ)
|
||||
|
||||
info := w.p.typIdx(typ, w.dict)
|
||||
w.rtypeInfo(info)
|
||||
}
|
||||
|
||||
func (w *writer) rtypeInfo(info typeInfo) {
|
||||
w.Sync(pkgbits.SyncRType)
|
||||
|
||||
info := w.p.typIdx(typ, w.dict)
|
||||
if w.Bool(info.derived) {
|
||||
w.Len(w.dict.rtypeIdx(info))
|
||||
} else {
|
||||
@ -2218,11 +2222,11 @@ func (w *writer) itab(typ, iface types2.Type) {
|
||||
|
||||
typInfo := w.p.typIdx(typ, w.dict)
|
||||
ifaceInfo := w.p.typIdx(iface, w.dict)
|
||||
|
||||
w.rtypeInfo(typInfo)
|
||||
w.rtypeInfo(ifaceInfo)
|
||||
if w.Bool(typInfo.derived || ifaceInfo.derived) {
|
||||
w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
|
||||
} else {
|
||||
w.typInfo(typInfo)
|
||||
w.typInfo(ifaceInfo)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user