go/go2go: cache type instantiations

Change-Id: Ie239e6ac7cfabf472970cd2aeddf337bcc242043
This commit is contained in:
Ian Lance Taylor 2020-01-24 13:50:09 -08:00 committed by Robert Griesemer
parent a480c1b795
commit 9ceb91ef5f
3 changed files with 41 additions and 11 deletions

View File

@ -14,13 +14,15 @@ import (
// We can look them up either with a types.Object associated with an ast.Ident,
// or with a types.TypeParam.
type typeArgs struct {
types []types.Type // type arguments in order
toAST map[types.Object]ast.Expr
toTyp map[*types.TypeParam]types.Type
}
// newTypeArgs returns a new typeArgs value.
func newTypeArgs() *typeArgs {
func newTypeArgs(typeTypes []types.Type) *typeArgs {
return &typeArgs{
types: typeTypes,
toAST: make(map[types.Object]ast.Expr),
toTyp: make(map[*types.TypeParam]types.Type),
}
@ -56,7 +58,7 @@ func (t *translator) instantiateFunction(fnident *ast.Ident, astTypes []ast.Expr
return nil, err
}
ta := newTypeArgs()
ta := newTypeArgs(typeTypes)
for i, tf := range decl.Type.TParams.List {
for _, tn := range tf.Names {
obj, ok := t.info.Defs[tn]

View File

@ -41,11 +41,12 @@ func isParameterizedFuncDecl(fd *ast.FuncDecl) bool {
// A translator is used to translate a file from Go with contracts to Go 1.
type translator struct {
info *types.Info
types map[ast.Expr]types.Type
idToFunc map[types.Object]*ast.FuncDecl
instantiations map[*ast.Ident][]*instantiation
newDecls []ast.Decl
info *types.Info
types map[ast.Expr]types.Type
idToFunc map[types.Object]*ast.FuncDecl
instantiations map[*ast.Ident][]*instantiation
newDecls []ast.Decl
typeInstantiations map[types.Type][]*typeInstantiation
}
// An instantiation is a single instantiation of a function.
@ -54,6 +55,12 @@ type instantiation struct {
decl *ast.Ident
}
// A typeInstantiation is a single instantiation of a type.
type typeInstantiation struct {
types []types.Type
typ types.Type
}
// rewrite rewrites the contents of one file.
func rewriteFile(dir string, fset *token.FileSet, info *types.Info, idToFunc map[types.Object]*ast.FuncDecl, filename string, file *ast.File) (err error) {
if err := rewriteAST(info, idToFunc, file); err != nil {
@ -86,10 +93,11 @@ func rewriteFile(dir string, fset *token.FileSet, info *types.Info, idToFunc map
// rewriteAST rewrites the AST for a file.
func rewriteAST(info *types.Info, idToFunc map[types.Object]*ast.FuncDecl, file *ast.File) (err error) {
t := translator{
info: info,
types: make(map[ast.Expr]types.Type),
idToFunc: idToFunc,
instantiations: make(map[*ast.Ident][]*instantiation),
info: info,
types: make(map[ast.Expr]types.Type),
idToFunc: idToFunc,
instantiations: make(map[*ast.Ident][]*instantiation),
typeInstantiations: make(map[types.Type][]*typeInstantiation),
}
return t.translate(file)
}

View File

@ -42,6 +42,26 @@ func (t *translator) setType(e ast.Expr, nt types.Type) {
// instantiateType instantiates typ using ta.
func (t *translator) instantiateType(ta *typeArgs, typ types.Type) types.Type {
if insts, ok := t.typeInstantiations[typ]; ok {
for _, inst := range insts {
if t.sameTypes(ta.types, inst.types) {
return inst.typ
}
}
}
ityp := t.doInstantiateType(ta, typ)
typinst := &typeInstantiation{
types: ta.types,
typ: ityp,
}
t.typeInstantiations[typ] = append(t.typeInstantiations[typ], typinst)
return ityp
}
// doInstantiateType does the work of instantiating typ using ta.
// This should only be called from instantiateType.
func (t *translator) doInstantiateType(ta *typeArgs, typ types.Type) types.Type {
switch typ := typ.(type) {
case *types.TypeParam:
if instType, ok := ta.typ(typ); ok {