8167431: javac takes too long time to resolve interface dependency
Reviewed-by: mcimadamore
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Tue Nov 01 10:14:42 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Tue Nov 01 10:51:53 2016 -0400
@@ -2850,20 +2850,64 @@
return undef;
}
+ public class CandidatesCache {
+ public Map<Entry, List<MethodSymbol>> cache = new WeakHashMap<>();
+
+ class Entry {
+ Type site;
+ MethodSymbol msym;
+
+ Entry(Type site, MethodSymbol msym) {
+ this.site = site;
+ this.msym = msym;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Entry) {
+ Entry e = (Entry)obj;
+ return e.msym == msym && isSameType(site, e.site);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Types.this.hashCode(site) & ~msym.hashCode();
+ }
+ }
+
+ public List<MethodSymbol> get(Entry e) {
+ return cache.get(e);
+ }
+
+ public void put(Entry e, List<MethodSymbol> msymbols) {
+ cache.put(e, msymbols);
+ }
+ }
+
+ public CandidatesCache candidatesCache = new CandidatesCache();
//where
public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
- Filter<Symbol> filter = new MethodFilter(ms, site);
- List<MethodSymbol> candidates = List.nil();
+ CandidatesCache.Entry e = candidatesCache.new Entry(site, ms);
+ List<MethodSymbol> candidates = candidatesCache.get(e);
+ if (candidates == null) {
+ Filter<Symbol> filter = new MethodFilter(ms, site);
+ List<MethodSymbol> candidates2 = List.nil();
for (Symbol s : membersClosure(site, false).getSymbols(filter)) {
if (!site.tsym.isInterface() && !s.owner.isInterface()) {
return List.of((MethodSymbol)s);
- } else if (!candidates.contains(s)) {
- candidates = candidates.prepend((MethodSymbol)s);
+ } else if (!candidates2.contains(s)) {
+ candidates2 = candidates2.prepend((MethodSymbol)s);
}
}
- return prune(candidates);
+ candidates = prune(candidates2);
+ candidatesCache.put(e, candidates);
}
+ return candidates;
+ }
public List<MethodSymbol> prune(List<MethodSymbol> methods) {
ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java Tue Nov 01 10:14:42 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java Tue Nov 01 10:51:53 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,9 +62,9 @@
}
public O next() {
- if (!hasNext())
+ if (currentIterator == EMPTY && !hasNext()) {
throw new NoSuchElementException();
-
+ }
return currentIterator.next();
}