From 4df74776da6ee13500bb85c70afa7bcc93fcf8e6 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 10 Jul 2013 18:01:11 -0400 Subject: [PATCH] go.tools/ssa: de-dup the creation of method sets, using typemap. Yields a ~20% improvement in SSA construction time. Also: better names for promotion wrapper functions. R=gri CC=golang-dev https://golang.org/cl/11050043 --- go/types/typemap/typemap_test.go | 5 +++-- ssa/create.go | 1 - ssa/promote.go | 16 ++++++---------- ssa/ssa.go | 3 ++- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/go/types/typemap/typemap_test.go b/go/types/typemap/typemap_test.go index 295c82c6..9230af7f 100644 --- a/go/types/typemap/typemap_test.go +++ b/go/types/typemap/typemap_test.go @@ -6,10 +6,11 @@ package typemap_test // (e.g. all types generated by type-checking some body of real code). import ( - "code.google.com/p/go.tools/go/types" - "code.google.com/p/go.tools/go/types/typemap" "go/ast" "testing" + + "code.google.com/p/go.tools/go/types" + "code.google.com/p/go.tools/go/types/typemap" ) var ( diff --git a/ssa/create.go b/ssa/create.go index 079bcf93..2f709512 100644 --- a/ssa/create.go +++ b/ssa/create.go @@ -39,7 +39,6 @@ func NewProgram(fset *token.FileSet, mode BuilderMode) *Program { PackagesByPath: make(map[string]*Package), packages: make(map[*types.Package]*Package), builtins: make(map[types.Object]*Builtin), - methodSets: make(map[types.Type]MethodSet), concreteMethods: make(map[*types.Func]*Function), indirectionWrappers: make(map[*Function]*Function), boundMethodWrappers: make(map[*Function]*Function), diff --git a/ssa/promote.go b/ssa/promote.go index d6ef27dc..538265a8 100644 --- a/ssa/promote.go +++ b/ssa/promote.go @@ -81,14 +81,13 @@ type candidate struct { path *anonFieldPath // desugared selector path } -// For debugging. func (c candidate) String() string { s := "" // Inefficient! for p := c.path; p != nil; p = p.tail { s = "." + p.field.Name() + s } - return "@" + s + "." + c.method.Name() + return s + "." + c.method.Name() } // ptrRecv returns true if this candidate has a pointer receiver. @@ -110,15 +109,12 @@ func (p *Program) MethodSet(typ types.Type) MethodSet { p.methodsMu.Lock() defer p.methodsMu.Unlock() - // TODO(adonovan): Using Types as map keys doesn't properly - // de-dup. e.g. *Named are canonical but *Struct and - // others are not. Need to de-dup using typemap.T. - mset := p.methodSets[typ] + mset := p.methodSets.At(typ) if mset == nil { mset = buildMethodSet(p, typ) - p.methodSets[typ] = mset + p.methodSets.Set(typ, mset) } - return mset + return mset.(MethodSet) } // buildMethodSet computes the concrete method set for type typ. @@ -282,12 +278,12 @@ func promotionWrapper(prog *Program, typ types.Type, cand *candidate) *Function // TODO(adonovan): consult memoization cache keyed by (typ, cand). // Needs typemap. Also needs hash/eq functions for 'candidate'. if prog.mode&LogSource != 0 { - defer logStack("promotionWrapper %s, %s, type %s", typ, cand, sig)() + defer logStack("promotionWrapper (%s)%s, type %s", typ, cand, sig)() } fn := &Function{ name: cand.method.Name(), Signature: sig, - Synthetic: "promotion wrapper for " + cand.String(), + Synthetic: fmt.Sprintf("promotion wrapper for (%s)%s", typ, cand), Prog: prog, pos: cand.method.Pos(), } diff --git a/ssa/ssa.go b/ssa/ssa.go index 0ffd166f..fc841eda 100644 --- a/ssa/ssa.go +++ b/ssa/ssa.go @@ -11,6 +11,7 @@ import ( "code.google.com/p/go.tools/go/exact" "code.google.com/p/go.tools/go/types" + "code.google.com/p/go.tools/go/types/typemap" "code.google.com/p/go.tools/importer" ) @@ -25,7 +26,7 @@ type Program struct { mode BuilderMode // set of mode bits for SSA construction methodsMu sync.Mutex // guards the following maps: - methodSets map[types.Type]MethodSet // concrete method set each type [TODO(adonovan): de-dup] + methodSets typemap.M // maps type to its concrete MethodSet indirectionWrappers map[*Function]*Function // func(*T) wrappers for T-methods boundMethodWrappers map[*Function]*Function // wrappers for curried x.Method closures ifaceMethodWrappers map[*types.Func]*Function // wrappers for curried I.Method functions