Skip to content

Commit 9fc09d2

Browse files
committed
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 <[email protected]> Run-TryBot: Matthew Dempsky <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent 3e11e61 commit 9fc09d2

File tree

2 files changed

+39
-39
lines changed

2 files changed

+39
-39
lines changed

src/cmd/compile/internal/noder/reader.go

+31-35
Original file line numberDiff line numberDiff line change
@@ -1386,27 +1386,18 @@ func (pr *pkgReader) dictNameOf(dict *readerDict) *ir.Name {
13861386
reflectdata.MarkTypeUsedInInterface(typ, lsym)
13871387
}
13881388

1389-
// For each (typ, iface) pair, we write *runtime._type pointers
1390-
// for typ and iface, as well as the *runtime.itab pointer for the
1391-
// pair. This is wasteful, but it simplifies worrying about tricky
1392-
// cases like instantiating type parameters with interface types.
1393-
//
1394-
// TODO(mdempsky): Add the needed *runtime._type pointers into the
1395-
// rtypes section above instead, and omit itabs entries when we
1396-
// statically know it won't be needed.
1389+
// For each (typ, iface) pair, we write the *runtime.itab pointer
1390+
// for the pair. For pairs that don't actually require an itab
1391+
// (i.e., typ is an interface, or iface is an empty interface), we
1392+
// write a nil pointer instead. This is wasteful, but rare in
1393+
// practice (e.g., instantiating a type parameter with an interface
1394+
// type).
13971395
assertOffset("itabs", dict.itabsOffset())
13981396
for _, info := range dict.itabs {
13991397
typ := pr.typIdx(info.typ, dict, true)
14001398
iface := pr.typIdx(info.iface, dict, true)
14011399

1402-
if !iface.IsInterface() {
1403-
ot += 3 * types.PtrSize
1404-
continue
1405-
}
1406-
1407-
ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(typ), 0)
1408-
ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(iface), 0)
1409-
if !typ.IsInterface() && !iface.IsEmptyInterface() {
1400+
if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
14101401
ot = objw.SymPtr(lsym, ot, reflectdata.ITabLsym(typ, iface), 0)
14111402
} else {
14121403
ot += types.PtrSize
@@ -1452,7 +1443,7 @@ func (dict *readerDict) itabsOffset() int {
14521443
// numWords returns the total number of words that comprise dict's
14531444
// runtime dictionary variable.
14541445
func (dict *readerDict) numWords() int64 {
1455-
return int64(dict.itabsOffset() + 3*len(dict.itabs))
1446+
return int64(dict.itabsOffset() + len(dict.itabs))
14561447
}
14571448

14581449
// varType returns the type of dict's runtime dictionary variable.
@@ -3152,28 +3143,35 @@ func (r *reader) varDictIndex(name *ir.Name) {
31523143
}
31533144
}
31543145

3146+
// itab returns a (typ, iface) pair of types.
3147+
//
3148+
// typRType and ifaceRType are expressions that evaluate to the
3149+
// *runtime._type for typ and iface, respectively.
3150+
//
3151+
// If typ is a concrete type and iface is a non-empty interface type,
3152+
// then itab is an expression that evaluates to the *runtime.itab for
3153+
// the pair. Otherwise, itab is nil.
31553154
func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3156-
if r.Bool() { // derived types
3157-
idx := r.Len()
3158-
info := r.dict.itabs[idx]
3159-
typ = r.p.typIdx(info.typ, r.dict, true)
3160-
typRType = r.rttiWord(pos, r.dict.itabsOffset()+3*idx)
3161-
iface = r.p.typIdx(info.iface, r.dict, true)
3162-
ifaceRType = r.rttiWord(pos, r.dict.itabsOffset()+3*idx+1)
3163-
itab = r.rttiWord(pos, r.dict.itabsOffset()+3*idx+2)
3164-
return
3155+
typ, typRType = r.rtype0(pos)
3156+
iface, ifaceRType = r.rtype0(pos)
3157+
3158+
idx := -1
3159+
if r.Bool() {
3160+
idx = r.Len()
31653161
}
31663162

3167-
typ = r.typ()
3168-
iface = r.typ()
3169-
if iface.IsInterface() {
3170-
typRType = reflectdata.TypePtrAt(pos, typ)
3171-
ifaceRType = reflectdata.TypePtrAt(pos, iface)
3172-
if !typ.IsInterface() && !iface.IsEmptyInterface() {
3163+
if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3164+
if idx >= 0 {
3165+
itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3166+
} else {
3167+
base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3168+
base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3169+
31733170
lsym := reflectdata.ITabLsym(typ, iface)
31743171
itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
31753172
}
31763173
}
3174+
31773175
return
31783176
}
31793177

@@ -3215,9 +3213,7 @@ func (r *reader) exprType() ir.Node {
32153213

32163214
if r.Bool() {
32173215
typ, rtype, _, _, itab = r.itab(pos)
3218-
if typ.IsInterface() {
3219-
itab = nil
3220-
} else {
3216+
if !typ.IsInterface() {
32213217
rtype = nil // TODO(mdempsky): Leave set?
32223218
}
32233219
} else {

src/cmd/compile/internal/noder/writer.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -2183,9 +2183,13 @@ func (w *writer) exprs(exprs []syntax.Expr) {
21832183
func (w *writer) rtype(typ types2.Type) {
21842184
typ = types2.Default(typ)
21852185

2186+
info := w.p.typIdx(typ, w.dict)
2187+
w.rtypeInfo(info)
2188+
}
2189+
2190+
func (w *writer) rtypeInfo(info typeInfo) {
21862191
w.Sync(pkgbits.SyncRType)
21872192

2188-
info := w.p.typIdx(typ, w.dict)
21892193
if w.Bool(info.derived) {
21902194
w.Len(w.dict.rtypeIdx(info))
21912195
} else {
@@ -2218,11 +2222,11 @@ func (w *writer) itab(typ, iface types2.Type) {
22182222

22192223
typInfo := w.p.typIdx(typ, w.dict)
22202224
ifaceInfo := w.p.typIdx(iface, w.dict)
2225+
2226+
w.rtypeInfo(typInfo)
2227+
w.rtypeInfo(ifaceInfo)
22212228
if w.Bool(typInfo.derived || ifaceInfo.derived) {
22222229
w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
2223-
} else {
2224-
w.typInfo(typInfo)
2225-
w.typInfo(ifaceInfo)
22262230
}
22272231
}
22282232

0 commit comments

Comments
 (0)