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).
|
// (e.g. all types generated by type-checking some body of real code).
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.tools/go/types"
|
|
||||||
"code.google.com/p/go.tools/go/types/typemap"
|
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.google.com/p/go.tools/go/types"
|
||||||
|
"code.google.com/p/go.tools/go/types/typemap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
|
||||||
PackagesByPath: make(map[string]*Package),
|
PackagesByPath: make(map[string]*Package),
|
||||||
packages: make(map[*types.Package]*Package),
|
packages: make(map[*types.Package]*Package),
|
||||||
builtins: make(map[types.Object]*Builtin),
|
builtins: make(map[types.Object]*Builtin),
|
||||||
methodSets: make(map[types.Type]MethodSet),
|
|
||||||
concreteMethods: make(map[*types.Func]*Function),
|
concreteMethods: make(map[*types.Func]*Function),
|
||||||
indirectionWrappers: make(map[*Function]*Function),
|
indirectionWrappers: make(map[*Function]*Function),
|
||||||
boundMethodWrappers: make(map[*Function]*Function),
|
boundMethodWrappers: make(map[*Function]*Function),
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,13 @@ type candidate struct {
|
||||||
path *anonFieldPath // desugared selector path
|
path *anonFieldPath // desugared selector path
|
||||||
}
|
}
|
||||||
|
|
||||||
// For debugging.
|
|
||||||
func (c candidate) String() string {
|
func (c candidate) String() string {
|
||||||
s := ""
|
s := ""
|
||||||
// Inefficient!
|
// Inefficient!
|
||||||
for p := c.path; p != nil; p = p.tail {
|
for p := c.path; p != nil; p = p.tail {
|
||||||
s = "." + p.field.Name() + s
|
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.
|
// 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()
|
p.methodsMu.Lock()
|
||||||
defer p.methodsMu.Unlock()
|
defer p.methodsMu.Unlock()
|
||||||
|
|
||||||
// TODO(adonovan): Using Types as map keys doesn't properly
|
mset := p.methodSets.At(typ)
|
||||||
// de-dup. e.g. *Named are canonical but *Struct and
|
|
||||||
// others are not. Need to de-dup using typemap.T.
|
|
||||||
mset := p.methodSets[typ]
|
|
||||||
if mset == nil {
|
if mset == nil {
|
||||||
mset = buildMethodSet(p, typ)
|
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.
|
// 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).
|
// TODO(adonovan): consult memoization cache keyed by (typ, cand).
|
||||||
// Needs typemap. Also needs hash/eq functions for 'candidate'.
|
// Needs typemap. Also needs hash/eq functions for 'candidate'.
|
||||||
if prog.mode&LogSource != 0 {
|
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{
|
fn := &Function{
|
||||||
name: cand.method.Name(),
|
name: cand.method.Name(),
|
||||||
Signature: sig,
|
Signature: sig,
|
||||||
Synthetic: "promotion wrapper for " + cand.String(),
|
Synthetic: fmt.Sprintf("promotion wrapper for (%s)%s", typ, cand),
|
||||||
Prog: prog,
|
Prog: prog,
|
||||||
pos: cand.method.Pos(),
|
pos: cand.method.Pos(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/exact"
|
"code.google.com/p/go.tools/go/exact"
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
|
"code.google.com/p/go.tools/go/types/typemap"
|
||||||
"code.google.com/p/go.tools/importer"
|
"code.google.com/p/go.tools/importer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -25,7 +26,7 @@ type Program struct {
|
||||||
mode BuilderMode // set of mode bits for SSA construction
|
mode BuilderMode // set of mode bits for SSA construction
|
||||||
|
|
||||||
methodsMu sync.Mutex // guards the following maps:
|
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
|
indirectionWrappers map[*Function]*Function // func(*T) wrappers for T-methods
|
||||||
boundMethodWrappers map[*Function]*Function // wrappers for curried x.Method closures
|
boundMethodWrappers map[*Function]*Function // wrappers for curried x.Method closures
|
||||||
ifaceMethodWrappers map[*types.Func]*Function // wrappers for curried I.Method functions
|
ifaceMethodWrappers map[*types.Func]*Function // wrappers for curried I.Method functions
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue