langtools/src/share/classes/com/sun/tools/javac/code/Types.java
changeset 14725 65836e833f59
parent 14723 46aa71a5e4e0
child 14801 d66cab4ef397
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Nov 30 15:14:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Nov 30 15:14:48 2012 +0000
@@ -389,28 +389,6 @@
         }
 
         /**
-         * Scope filter used to skip methods that should be ignored during
-         * function interface conversion (such as methods overridden by
-         * j.l.Object)
-         */
-        class DescriptorFilter implements Filter<Symbol> {
-
-            TypeSymbol origin;
-
-            DescriptorFilter(TypeSymbol origin) {
-                this.origin = origin;
-            }
-
-            @Override
-            public boolean accepts(Symbol sym) {
-                return sym.kind == Kinds.MTH &&
-                        (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
-                        !overridesObjectMethod(origin, sym) &&
-                        (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
-            }
-        };
-
-        /**
          * Compute the function descriptor associated with a given functional interface
          */
         public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
@@ -577,6 +555,85 @@
     }
     // </editor-fold>
 
+   /**
+    * Scope filter used to skip methods that should be ignored (such as methods
+    * overridden by j.l.Object) during function interface conversion/marker interface checks
+    */
+    class DescriptorFilter implements Filter<Symbol> {
+
+       TypeSymbol origin;
+
+       DescriptorFilter(TypeSymbol origin) {
+           this.origin = origin;
+       }
+
+       @Override
+       public boolean accepts(Symbol sym) {
+           return sym.kind == Kinds.MTH &&
+                   (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
+                   !overridesObjectMethod(origin, sym) &&
+                   (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
+       }
+    };
+
+    // <editor-fold defaultstate="collapsed" desc="isMarker">
+
+    /**
+     * A cache that keeps track of marker interfaces
+     */
+    class MarkerCache {
+
+        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<TypeSymbol, Entry>();
+
+        class Entry {
+            final boolean isMarkerIntf;
+            final int prevMark;
+
+            public Entry(boolean isMarkerIntf,
+                    int prevMark) {
+                this.isMarkerIntf = isMarkerIntf;
+                this.prevMark = prevMark;
+            }
+
+            boolean matches(int mark) {
+                return  this.prevMark == mark;
+            }
+        }
+
+        boolean get(TypeSymbol origin) throws FunctionDescriptorLookupError {
+            Entry e = _map.get(origin);
+            CompoundScope members = membersClosure(origin.type, false);
+            if (e == null ||
+                    !e.matches(members.getMark())) {
+                boolean isMarkerIntf = isMarkerInterfaceInternal(origin, members);
+                _map.put(origin, new Entry(isMarkerIntf, members.getMark()));
+                return isMarkerIntf;
+            }
+            else {
+                return e.isMarkerIntf;
+            }
+        }
+
+        /**
+         * Is given symbol a marker interface
+         */
+        public boolean isMarkerInterfaceInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
+            return !origin.isInterface() ?
+                    false :
+                    !membersCache.getElements(new DescriptorFilter(origin)).iterator().hasNext();
+        }
+    }
+
+    private MarkerCache markerCache = new MarkerCache();
+
+    /**
+     * Is given type a marker interface?
+     */
+    public boolean isMarkerInterface(Type site) {
+        return markerCache.get(site.tsym);
+    }
+    // </editor-fold>
+
     // <editor-fold defaultstate="collapsed" desc="isSubtype">
     /**
      * Is t an unchecked subtype of s?
@@ -1955,45 +2012,28 @@
      * @param supertype         is objectType if all bounds are interfaces,
      *                          null otherwise.
      */
-    public Type makeCompoundType(List<Type> bounds,
-                                 Type supertype) {
+    public Type makeCompoundType(List<Type> bounds) {
+        return makeCompoundType(bounds, bounds.head.tsym.isInterface());
+    }
+    public Type makeCompoundType(List<Type> bounds, boolean allInterfaces) {
+        Assert.check(bounds.nonEmpty());
+        Type firstExplicitBound = bounds.head;
+        if (allInterfaces) {
+            bounds = bounds.prepend(syms.objectType);
+        }
         ClassSymbol bc =
             new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC,
                             Type.moreInfo
                                 ? names.fromString(bounds.toString())
                                 : names.empty,
+                            null,
                             syms.noSymbol);
-        if (bounds.head.tag == TYPEVAR)
-            // error condition, recover
-                bc.erasure_field = syms.objectType;
-            else
-                bc.erasure_field = erasure(bounds.head);
-            bc.members_field = new Scope(bc);
-        ClassType bt = (ClassType)bc.type;
-        bt.allparams_field = List.nil();
-        if (supertype != null) {
-            bt.supertype_field = supertype;
-            bt.interfaces_field = bounds;
-        } else {
-            bt.supertype_field = bounds.head;
-            bt.interfaces_field = bounds.tail;
-        }
-        Assert.check(bt.supertype_field.tsym.completer != null
-                || !bt.supertype_field.isInterface(),
-            bt.supertype_field);
-        return bt;
-    }
-
-    /**
-     * Same as {@link #makeCompoundType(List,Type)}, except that the
-     * second parameter is computed directly. Note that this might
-     * cause a symbol completion.  Hence, this version of
-     * makeCompoundType may not be called during a classfile read.
-     */
-    public Type makeCompoundType(List<Type> bounds) {
-        Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ?
-            supertype(bounds.head) : null;
-        return makeCompoundType(bounds, supertype);
+        bc.type = new IntersectionClassType(bounds, bc, allInterfaces);
+        bc.erasure_field = (bounds.head.tag == TYPEVAR) ?
+                syms.objectType : // error condition, recover
+                erasure(firstExplicitBound);
+        bc.members_field = new Scope(bc);
+        return bc.type;
     }
 
     /**
@@ -2183,12 +2223,8 @@
      * @param supertype         is objectType if all bounds are interfaces,
      *                          null otherwise.
      */
-    public void setBounds(TypeVar t, List<Type> bounds, Type supertype) {
-        if (bounds.tail.isEmpty())
-            t.bound = bounds.head;
-        else
-            t.bound = makeCompoundType(bounds, supertype);
-        t.rank_field = -1;
+    public void setBounds(TypeVar t, List<Type> bounds) {
+        setBounds(t, bounds, bounds.head.tsym.isInterface());
     }
 
     /**
@@ -2200,10 +2236,10 @@
      * Note that this check might cause a symbol completion. Hence, this version of
      * setBounds may not be called during a classfile read.
      */
-    public void setBounds(TypeVar t, List<Type> bounds) {
-        Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ?
-            syms.objectType : null;
-        setBounds(t, bounds, supertype);
+    public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) {
+        t.bound = bounds.tail.isEmpty() ?
+                bounds.head :
+                makeCompoundType(bounds, allInterfaces);
         t.rank_field = -1;
     }
     // </editor-fold>
@@ -2213,7 +2249,7 @@
      * Return list of bounds of the given type variable.
      */
     public List<Type> getBounds(TypeVar t) {
-                if (t.bound.hasTag(NONE))
+        if (t.bound.hasTag(NONE))
             return List.nil();
         else if (t.bound.isErroneous() || !t.bound.isCompound())
             return List.of(t.bound);
@@ -3312,8 +3348,7 @@
                     if (arraySuperType == null) {
                         // JLS 10.8: all arrays implement Cloneable and Serializable.
                         arraySuperType = makeCompoundType(List.of(syms.serializableType,
-                                                                  syms.cloneableType),
-                                                          syms.objectType);
+                                                                  syms.cloneableType), true);
                     }
                 }
             }