6827648: Extremely slow compilation time for visitor pattern code + generics

Thu, 30 Jul 2009 10:29:53 +0100

author
mcimadamore
date
Thu, 30 Jul 2009 10:29:53 +0100
changeset 341
85fecace920b
parent 340
c2dfab9e2f39
child 342
b1e027181dd4

6827648: Extremely slow compilation time for visitor pattern code + generics
Summary: Javac unnecessarily recomputates type-substitutions multiple times
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Types.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Jul 29 13:26:26 2009 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jul 30 10:29:53 2009 +0100
     1.3 @@ -1197,21 +1197,9 @@
     1.4           *  as possible implementations.
     1.5           */
     1.6          public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
     1.7 -            for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
     1.8 -                while (t.tag == TYPEVAR)
     1.9 -                    t = t.getUpperBound();
    1.10 -                TypeSymbol c = t.tsym;
    1.11 -                for (Scope.Entry e = c.members().lookup(name);
    1.12 -                     e.scope != null;
    1.13 -                     e = e.next()) {
    1.14 -                    if (e.sym.kind == MTH) {
    1.15 -                        MethodSymbol m = (MethodSymbol) e.sym;
    1.16 -                        if (m.overrides(this, origin, types, checkResult) &&
    1.17 -                            (m.flags() & SYNTHETIC) == 0)
    1.18 -                            return m;
    1.19 -                    }
    1.20 -                }
    1.21 -            }
    1.22 +            MethodSymbol res = types.implementation(this, origin, types, checkResult);
    1.23 +            if (res != null)
    1.24 +                return res;
    1.25              // if origin is derived from a raw type, we might have missed
    1.26              // an implementation because we do not know enough about instantiations.
    1.27              // in this case continue with the supertype as origin.
     2.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Jul 29 13:26:26 2009 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Jul 30 10:29:53 2009 +0100
     2.3 @@ -25,10 +25,9 @@
     2.4  
     2.5  package com.sun.tools.javac.code;
     2.6  
     2.7 +import java.lang.ref.SoftReference;
     2.8  import java.util.*;
     2.9  
    2.10 -import com.sun.tools.javac.api.Messages;
    2.11 -
    2.12  import com.sun.tools.javac.util.*;
    2.13  import com.sun.tools.javac.util.List;
    2.14  
    2.15 @@ -1442,7 +1441,7 @@
    2.16          return (sym.flags() & STATIC) != 0
    2.17              ? sym.type
    2.18              : memberType.visit(t, sym);
    2.19 -    }
    2.20 +        }
    2.21      // where
    2.22          private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {
    2.23  
    2.24 @@ -1552,7 +1551,7 @@
    2.25              return t; /* fast special case */
    2.26          else
    2.27              return erasure.visit(t, recurse);
    2.28 -    }
    2.29 +        }
    2.30      // where
    2.31          private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
    2.32              public Type visitType(Type t, Boolean recurse) {
    2.33 @@ -1946,6 +1945,45 @@
    2.34              hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
    2.35      }
    2.36  
    2.37 +    private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_check =
    2.38 +            new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
    2.39 +
    2.40 +    private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_nocheck =
    2.41 +            new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
    2.42 +
    2.43 +    public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult) {
    2.44 +        Map<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache = checkResult ?
    2.45 +            implCache_check : implCache_nocheck;
    2.46 +        SoftReference<Map<TypeSymbol, MethodSymbol>> ref_cache = implCache.get(ms);
    2.47 +        Map<TypeSymbol, MethodSymbol> cache = ref_cache != null ? ref_cache.get() : null;
    2.48 +        if (cache == null) {
    2.49 +            cache = new HashMap<TypeSymbol, MethodSymbol>();
    2.50 +            implCache.put(ms, new SoftReference<Map<TypeSymbol, MethodSymbol>>(cache));
    2.51 +        }
    2.52 +        MethodSymbol impl = cache.get(origin);
    2.53 +        if (impl == null) {
    2.54 +            for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
    2.55 +                while (t.tag == TYPEVAR)
    2.56 +                    t = t.getUpperBound();
    2.57 +                TypeSymbol c = t.tsym;
    2.58 +                for (Scope.Entry e = c.members().lookup(ms.name);
    2.59 +                     e.scope != null;
    2.60 +                     e = e.next()) {
    2.61 +                    if (e.sym.kind == Kinds.MTH) {
    2.62 +                        MethodSymbol m = (MethodSymbol) e.sym;
    2.63 +                        if (m.overrides(ms, origin, types, checkResult) &&
    2.64 +                            (m.flags() & SYNTHETIC) == 0) {
    2.65 +                            impl = m;
    2.66 +                            cache.put(origin, m);
    2.67 +                            return impl;
    2.68 +                        }
    2.69 +                    }
    2.70 +                }
    2.71 +            }
    2.72 +        }
    2.73 +        return impl;
    2.74 +    }
    2.75 +
    2.76      /**
    2.77       * Does t have the same arguments as s?  It is assumed that both
    2.78       * types are (possibly polymorphic) method types.  Monomorphic

mercurial