mirror of
https://github.com/golang/go
synced 2024-11-17 21:04:43 -07:00
cmd/compile: make typenamesym do less work
This is a re-roll of CL 39710, which broke deterministic builds. typenamesym is called from three places: typename, ngotype, and Type.Symbol. Only in typename do we actually need a Node. ngotype and Type.Symbol require only a Sym. And writing the newly created Node to Sym.Def is unsafe in a concurrent backend. Rather than use a mutex protect to Sym.Def, make typenamesym not touch Sym.Def. The assignment to Sym.Def was serving a second purpose, namely to prevent duplicate entries on signatlist. Preserve that functionality by switching signatlist to a map. This in turn requires that we sort signatlist when exporting it, to preserve reproducibility. We sort using exactly the same mechanism that the export code (dtypesym) uses. Failure to do that led to non-deterministic builds (#19872). Since we've already calculated the Type's export name, we could pass it to dtypesym, sparing it a bit of work. That can be done as a future optimization. Updates #15756 name old alloc/op new alloc/op delta Template 39.2MB ± 0% 39.3MB ± 0% ~ (p=0.075 n=10+10) Unicode 29.8MB ± 0% 29.8MB ± 0% ~ (p=0.393 n=10+10) GoTypes 113MB ± 0% 113MB ± 0% +0.06% (p=0.027 n=10+8) SSA 1.25GB ± 0% 1.25GB ± 0% +0.05% (p=0.000 n=8+10) Flate 25.3MB ± 0% 25.3MB ± 0% ~ (p=0.105 n=10+10) GoParser 31.7MB ± 0% 31.8MB ± 0% ~ (p=0.165 n=10+10) Reflect 78.2MB ± 0% 78.2MB ± 0% ~ (p=0.190 n=10+10) Tar 26.6MB ± 0% 26.6MB ± 0% ~ (p=0.481 n=10+10) XML 42.2MB ± 0% 42.2MB ± 0% ~ (p=0.968 n=10+9) name old allocs/op new allocs/op delta Template 384k ± 1% 386k ± 1% +0.43% (p=0.019 n=10+10) Unicode 320k ± 0% 321k ± 0% +0.36% (p=0.015 n=10+10) GoTypes 1.14M ± 0% 1.14M ± 0% +0.33% (p=0.000 n=10+8) SSA 9.69M ± 0% 9.71M ± 0% +0.18% (p=0.000 n=10+9) Flate 233k ± 1% 233k ± 1% ~ (p=0.481 n=10+10) GoParser 315k ± 1% 316k ± 1% ~ (p=0.113 n=9+10) Reflect 979k ± 0% 979k ± 0% ~ (p=0.971 n=10+10) Tar 250k ± 1% 250k ± 1% ~ (p=0.481 n=10+10) XML 391k ± 1% 392k ± 0% ~ (p=1.000 n=10+9) Change-Id: Ia9f21cc29c047021fa8a18c2a3d861a5146aefac Reviewed-on: https://go-review.googlesource.com/39915 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
5b38923eba
commit
6d9c77f5dd
@ -35,7 +35,7 @@ type ptabEntry struct {
|
||||
}
|
||||
|
||||
// runtime interface and reflection data structures
|
||||
var signatlist []*types.Type
|
||||
var signatlist = make(map[*types.Type]bool)
|
||||
var itabs []itabEntry
|
||||
var ptabs []ptabEntry
|
||||
|
||||
@ -906,15 +906,17 @@ func dcommontype(s *types.Sym, ot int, t *types.Type) int {
|
||||
return ot
|
||||
}
|
||||
|
||||
func typesym(t *types.Type) *types.Sym {
|
||||
func typesymname(t *types.Type) string {
|
||||
name := t.ShortString()
|
||||
|
||||
// Use a separate symbol name for Noalg types for #17752.
|
||||
if a, bad := algtype1(t); a == ANOEQ && bad.Noalg() {
|
||||
name = "noalg." + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
return typepkg.Lookup(name)
|
||||
func typesym(t *types.Type) *types.Sym {
|
||||
return typepkg.Lookup(typesymname(t))
|
||||
}
|
||||
|
||||
// tracksym returns the symbol for tracking use of field/method f, assumed
|
||||
@ -934,24 +936,23 @@ func typesymprefix(prefix string, t *types.Type) *types.Sym {
|
||||
|
||||
func typenamesym(t *types.Type) *types.Sym {
|
||||
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
|
||||
Fatalf("typename %v", t)
|
||||
Fatalf("typenamesym %v", t)
|
||||
}
|
||||
s := typesym(t)
|
||||
addsignat(t)
|
||||
return s
|
||||
}
|
||||
|
||||
func typename(t *types.Type) *Node {
|
||||
s := typenamesym(t)
|
||||
if s.Def == nil {
|
||||
n := newnamel(src.NoXPos, s)
|
||||
n.Type = types.Types[TUINT8]
|
||||
n.Class = PEXTERN
|
||||
n.Typecheck = 1
|
||||
s.Def = asTypesNode(n)
|
||||
|
||||
signatlist = append(signatlist, t)
|
||||
}
|
||||
|
||||
return asNode(s.Def).Sym
|
||||
}
|
||||
|
||||
func typename(t *types.Type) *Node {
|
||||
s := typenamesym(t)
|
||||
n := nod(OADDR, asNode(s.Def), nil)
|
||||
n.Type = types.NewPtr(asNode(s.Def).Type)
|
||||
n.SetAddable(true)
|
||||
@ -1075,14 +1076,18 @@ func needkeyupdate(t *types.Type) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func dtypesym(t *types.Type) *types.Sym {
|
||||
// Replace byte, rune aliases with real type.
|
||||
// They've been separate internally to make error messages
|
||||
// better, but we have to merge them in the reflect tables.
|
||||
// formalType replaces byte and rune aliases with real types.
|
||||
// They've been separate internally to make error messages
|
||||
// better, but we have to merge them in the reflect tables.
|
||||
func formalType(t *types.Type) *types.Type {
|
||||
if t == types.Bytetype || t == types.Runetype {
|
||||
t = types.Types[t.Etype]
|
||||
return types.Types[t.Etype]
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func dtypesym(t *types.Type) *types.Sym {
|
||||
t = formalType(t)
|
||||
if t.IsUntyped() {
|
||||
Fatalf("dtypesym %v", t)
|
||||
}
|
||||
@ -1418,21 +1423,35 @@ func itabsym(it *obj.LSym, offset int64) *obj.LSym {
|
||||
return syms[methodnum]
|
||||
}
|
||||
|
||||
func addsignat(t *types.Type) {
|
||||
signatlist[formalType(t)] = true
|
||||
}
|
||||
|
||||
func dumptypestructs() {
|
||||
// copy types from externdcl list to signatlist
|
||||
for _, n := range externdcl {
|
||||
if n.Op == OTYPE {
|
||||
signatlist = append(signatlist, n.Type)
|
||||
addsignat(n.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// Process signatlist. This can't use range, as entries are
|
||||
// added to the list while it is being processed.
|
||||
for i := 0; i < len(signatlist); i++ {
|
||||
t := signatlist[i]
|
||||
dtypesym(t)
|
||||
if t.Sym != nil {
|
||||
dtypesym(types.NewPtr(t))
|
||||
// Process signatlist. Use a loop, as dtypesym adds
|
||||
// entries to signatlist while it is being processed.
|
||||
signats := make([]typeAndStr, len(signatlist))
|
||||
for len(signatlist) > 0 {
|
||||
signats = signats[:0]
|
||||
// Transfer entries to a slice and sort, for reproducible builds.
|
||||
for t := range signatlist {
|
||||
signats = append(signats, typeAndStr{t: t, s: typesymname(t)})
|
||||
delete(signatlist, t)
|
||||
}
|
||||
sort.Sort(typesByString(signats))
|
||||
for _, ts := range signats {
|
||||
t := ts.t
|
||||
dtypesym(t)
|
||||
if t.Sym != nil {
|
||||
dtypesym(types.NewPtr(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1528,6 +1547,17 @@ func dumptypestructs() {
|
||||
}
|
||||
}
|
||||
|
||||
type typeAndStr struct {
|
||||
t *types.Type
|
||||
s string
|
||||
}
|
||||
|
||||
type typesByString []typeAndStr
|
||||
|
||||
func (a typesByString) Len() int { return len(a) }
|
||||
func (a typesByString) Less(i, j int) bool { return a[i].s < a[j].s }
|
||||
func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type pkgByPath []*types.Pkg
|
||||
|
||||
func (a pkgByPath) Len() int { return len(a) }
|
||||
|
@ -927,6 +927,8 @@ func (r *Sym) cmpsym(s *Sym) ssa.Cmp {
|
||||
// cmp compares two *Types t and x, returning ssa.CMPlt,
|
||||
// ssa.CMPeq, ssa.CMPgt as t<x, t==x, t>x, for an arbitrary
|
||||
// and optimizer-centric notion of comparison.
|
||||
// TODO(josharian): make this safe for recursive interface types
|
||||
// and use in signatlist sorting. See issue 19869.
|
||||
func (t *Type) cmp(x *Type) ssa.Cmp {
|
||||
// This follows the structure of eqtype in subr.go
|
||||
// with two exceptions.
|
||||
|
Loading…
Reference in New Issue
Block a user