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
This commit is contained in:
parent
26d93d2e47
commit
4df74776da
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue