8167431: javac takes too long time to resolve interface dependency
authorvromero
Tue, 01 Nov 2016 10:51:53 -0400
changeset 41862 471a0cb1b986
parent 41861 8c58faf4f03b
child 41863 98b049c8b848
8167431: javac takes too long time to resolve interface dependency Reviewed-by: mcimadamore
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java
--- 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();
         }