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:
parent
54b80cfe2a
commit
59b2cbc448
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user