langtools/src/share/classes/com/sun/tools/javac/code/Types.java
changeset 6591 a953c8c6b85e
parent 6583 6410e8c9c848
child 6709 ade773eb432d
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Sep 06 12:55:09 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Sep 07 17:31:54 2010 +0100
@@ -1974,45 +1974,74 @@
             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));
+    // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
+    class ImplementationCache {
+
+        private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map =
+                new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>>();
+
+        class Entry {
+            final MethodSymbol cachedImpl;
+            final Filter<Symbol> implFilter;
+            final boolean checkResult;
+
+            public Entry(MethodSymbol cachedImpl,
+                    Filter<Symbol> scopeFilter,
+                    boolean checkResult) {
+                this.cachedImpl = cachedImpl;
+                this.implFilter = scopeFilter;
+                this.checkResult = checkResult;
+            }
+
+            boolean matches(Filter<Symbol> scopeFilter, boolean checkResult) {
+                return this.implFilter == scopeFilter &&
+                        this.checkResult == checkResult;
+            }
         }
-        MethodSymbol impl = cache.get(origin);
-        if (impl == null) {
+
+        MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
+            SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms);
+            Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null;
+            if (cache == null) {
+                cache = new HashMap<TypeSymbol, Entry>();
+                _map.put(ms, new SoftReference<Map<TypeSymbol, Entry>>(cache));
+            }
+            Entry e = cache.get(origin);
+            if (e == null ||
+                    !e.matches(implFilter, checkResult)) {
+                MethodSymbol impl = implementationInternal(ms, origin, Types.this, checkResult, implFilter);
+                cache.put(origin, new Entry(impl, implFilter, checkResult));
+                return impl;
+            }
+            else {
+                return e.cachedImpl;
+            }
+        }
+
+        private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
             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);
+                for (Scope.Entry e = c.members().lookup(ms.name, implFilter);
                      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;
-                        }
-                    }
+                    if (e.sym != null &&
+                             e.sym.overrides(ms, origin, types, checkResult))
+                        return (MethodSymbol)e.sym;
                 }
             }
+            return null;
         }
-        return impl;
     }
 
+    private ImplementationCache implCache = new ImplementationCache();
+
+    public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
+        return implCache.get(ms, origin, checkResult, implFilter);
+    }
+    // </editor-fold>
+
     /**
      * Does t have the same arguments as s?  It is assumed that both
      * types are (possibly polymorphic) method types.  Monomorphic