From a2a48069fee931af943161c9f8a9aace32811b7b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 10 Mar 2016 16:15:44 -0800 Subject: [PATCH] cmd/compile: rework how fieldtrack is implemented Shrinks gc.Type and gc.Func slightly. Passes "GOEXPERIMENT=fieldtrack ./all.bash" and "go test -a -toolexec='toolstash -cmp' -ldflags=-k=rsc.io/tmp/fieldtrack.tracked rsc.io/tmp/fieldtrack". Change-Id: I785fe8a18eb830d9867d34247e4cd41a6a7921d4 Reviewed-on: https://go-review.googlesource.com/20557 Run-TryBot: Matthew Dempsky Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/pgen.go | 11 +++++++++-- src/cmd/compile/internal/gc/reflect.go | 6 ++++-- src/cmd/compile/internal/gc/sizeof_test.go | 4 ++-- src/cmd/compile/internal/gc/syntax.go | 2 +- src/cmd/compile/internal/gc/type.go | 7 ++----- src/cmd/compile/internal/gc/walk.go | 19 +++++++++---------- 6 files changed, 27 insertions(+), 22 deletions(-) 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 - } - field.Lastfn = Curfn - field.Outer = n.Left.Type - if Isptr[field.Outer.Etype] { - field.Outer = field.Outer.Type + outer := n.Left.Type + if Isptr[outer.Etype] { + outer = 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 { -- 2.48.1