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

Javac unnecessarily recomputates type-substitutions multiple times

Reviewed-by: jjg
This commit is contained in:
Maurizio Cimadamore 2009-07-30 10:29:53 +01:00
parent 54b80cfe2a
commit 59b2cbc448
2 changed files with 45 additions and 19 deletions

View File

@ -1197,21 +1197,9 @@ public abstract class Symbol implements Element {
* as possible implementations.
*/
public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
while (t.tag == TYPEVAR)
t = t.getUpperBound();
TypeSymbol c = t.tsym;
for (Scope.Entry e = c.members().lookup(name);
e.scope != null;
e = e.next()) {
if (e.sym.kind == MTH) {
MethodSymbol m = (MethodSymbol) e.sym;
if (m.overrides(this, origin, types, checkResult) &&
(m.flags() & SYNTHETIC) == 0)
return m;
}
}
}
MethodSymbol res = types.implementation(this, origin, types, checkResult);
if (res != null)
return res;
// if origin is derived from a raw type, we might have missed
// an implementation because we do not know enough about instantiations.
// in this case continue with the supertype as origin.

View File

@ -25,10 +25,9 @@
package com.sun.tools.javac.code;
import java.lang.ref.SoftReference;
import java.util.*;
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
@ -1442,7 +1441,7 @@ public class Types {
return (sym.flags() & STATIC) != 0
? sym.type
: memberType.visit(t, sym);
}
}
// where
private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {
@ -1552,7 +1551,7 @@ public class Types {
return t; /* fast special case */
else
return erasure.visit(t, recurse);
}
}
// where
private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
public Type visitType(Type t, Boolean recurse) {
@ -1946,6 +1945,45 @@ public class Types {
hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
}
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_check =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_nocheck =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult) {
Map<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache = checkResult ?
implCache_check : implCache_nocheck;
SoftReference<Map<TypeSymbol, MethodSymbol>> ref_cache = implCache.get(ms);
Map<TypeSymbol, MethodSymbol> cache = ref_cache != null ? ref_cache.get() : null;
if (cache == null) {
cache = new HashMap<TypeSymbol, MethodSymbol>();
implCache.put(ms, new SoftReference<Map<TypeSymbol, MethodSymbol>>(cache));
}
MethodSymbol impl = cache.get(origin);
if (impl == null) {
for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
while (t.tag == TYPEVAR)
t = t.getUpperBound();
TypeSymbol c = t.tsym;
for (Scope.Entry e = c.members().lookup(ms.name);
e.scope != null;
e = e.next()) {
if (e.sym.kind == Kinds.MTH) {
MethodSymbol m = (MethodSymbol) e.sym;
if (m.overrides(ms, origin, types, checkResult) &&
(m.flags() & SYNTHETIC) == 0) {
impl = m;
cache.put(origin, m);
return impl;
}
}
}
}
}
return impl;
}
/**
* Does t have the same arguments as s? It is assumed that both
* types are (possibly polymorphic) method types. Monomorphic