diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index 75829aa2df..269a86c398 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -459,8 +459,15 @@ func compile(fn *Node) { gcargs := makefuncdatasym("gcargs·%d", obj.FUNCDATA_ArgsPointerMaps) gclocals := makefuncdatasym("gclocals·%d", obj.FUNCDATA_LocalsPointerMaps) - for _, t := range Curfn.Func.Fieldtrack { - gtrack(tracksym(t)) + if obj.Fieldtrack_enabled != 0 && len(Curfn.Func.FieldTrack) > 0 { + trackSyms := make([]*Sym, 0, len(Curfn.Func.FieldTrack)) + for sym := range Curfn.Func.FieldTrack { + trackSyms = append(trackSyms, sym) + } + sort.Sort(symByName(trackSyms)) + for _, sym := range trackSyms { + gtrack(sym) + } } for _, n := range fn.Func.Dcl { diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 5ca292c39e..05910b5226 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -798,8 +798,10 @@ func typesym(t *Type) *Sym { return Pkglookup(Tconv(t, obj.FmtLeft), typepkg) } -func tracksym(t *Type) *Sym { - return Pkglookup(Tconv(t.Outer, obj.FmtLeft)+"."+t.Sym.Name, trackpkg) +// tracksym returns the symbol for tracking use of field/method f, assumed +// to be a member of struct/interface type t. +func tracksym(t, f *Type) *Sym { + return Pkglookup(Tconv(t, obj.FmtLeft)+"."+f.Sym.Name, trackpkg) } func typelinksym(t *Type) *Sym { diff --git a/src/cmd/compile/internal/gc/sizeof_test.go b/src/cmd/compile/internal/gc/sizeof_test.go index 489dfaa6f8..29e51e5c08 100644 --- a/src/cmd/compile/internal/gc/sizeof_test.go +++ b/src/cmd/compile/internal/gc/sizeof_test.go @@ -23,11 +23,11 @@ func TestSizeof(t *testing.T) { _64bit uintptr // size on 64bit platforms }{ {Flow{}, 52, 88}, - {Func{}, 104, 184}, + {Func{}, 96, 168}, {Name{}, 52, 80}, {Node{}, 92, 144}, {Sym{}, 60, 112}, - {Type{}, 144, 240}, + {Type{}, 136, 224}, } for _, tt := range tests { diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 8831143e16..2ddc8cbbab 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -156,7 +156,7 @@ type Func struct { Inldcl Nodes // copy of dcl for use in inlining Closgen int Outerfunc *Node - Fieldtrack []*Type + FieldTrack map[*Sym]struct{} Outer *Node // outer func for closure Ntype *Node // signature Top int // top context (Ecall, Eproc, etc) diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index a8b52201a3..2b7010a038 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -141,9 +141,8 @@ type Type struct { Width int64 // offset in TFIELD, width in all others // TFIELD - Down *Type // next struct field, also key type in TMAP - Outer *Type // outer struct - Note *string // literal string annotation + Down *Type // next struct field, also key type in TMAP + Note *string // literal string annotation // TARRAY Bound int64 // negative is slice @@ -159,8 +158,6 @@ type Type struct { // for TFORW, where to copy the eventual value to Copyto []*Node - - Lastfn *Node // for usefield } // typ returns a new Type of the specified kind. diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 0284fb613c..fe9b0e5dc7 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -3838,23 +3838,22 @@ func usefield(n *Node) { return } - // dedup on list - if field.Lastfn == Curfn { - return + outer := n.Left.Type + if Isptr[outer.Etype] { + outer = outer.Type } - field.Lastfn = Curfn - field.Outer = n.Left.Type - if Isptr[field.Outer.Etype] { - field.Outer = field.Outer.Type - } - if field.Outer.Sym == nil { + if outer.Sym == nil { Yyerror("tracked field must be in named struct type") } if !exportname(field.Sym.Name) { Yyerror("tracked field must be exported (upper case)") } - Curfn.Func.Fieldtrack = append(Curfn.Func.Fieldtrack, field) + sym := tracksym(outer, field) + if Curfn.Func.FieldTrack == nil { + Curfn.Func.FieldTrack = make(map[*Sym]struct{}) + } + Curfn.Func.FieldTrack[sym] = struct{}{} } func candiscardlist(l Nodes) bool {