1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Fri Nov 30 15:14:36 2012 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Fri Nov 30 15:14:48 2012 +0000 1.3 @@ -389,28 +389,6 @@ 1.4 } 1.5 1.6 /** 1.7 - * Scope filter used to skip methods that should be ignored during 1.8 - * function interface conversion (such as methods overridden by 1.9 - * j.l.Object) 1.10 - */ 1.11 - class DescriptorFilter implements Filter<Symbol> { 1.12 - 1.13 - TypeSymbol origin; 1.14 - 1.15 - DescriptorFilter(TypeSymbol origin) { 1.16 - this.origin = origin; 1.17 - } 1.18 - 1.19 - @Override 1.20 - public boolean accepts(Symbol sym) { 1.21 - return sym.kind == Kinds.MTH && 1.22 - (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && 1.23 - !overridesObjectMethod(origin, sym) && 1.24 - (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; 1.25 - } 1.26 - }; 1.27 - 1.28 - /** 1.29 * Compute the function descriptor associated with a given functional interface 1.30 */ 1.31 public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError { 1.32 @@ -577,6 +555,85 @@ 1.33 } 1.34 // </editor-fold> 1.35 1.36 + /** 1.37 + * Scope filter used to skip methods that should be ignored (such as methods 1.38 + * overridden by j.l.Object) during function interface conversion/marker interface checks 1.39 + */ 1.40 + class DescriptorFilter implements Filter<Symbol> { 1.41 + 1.42 + TypeSymbol origin; 1.43 + 1.44 + DescriptorFilter(TypeSymbol origin) { 1.45 + this.origin = origin; 1.46 + } 1.47 + 1.48 + @Override 1.49 + public boolean accepts(Symbol sym) { 1.50 + return sym.kind == Kinds.MTH && 1.51 + (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && 1.52 + !overridesObjectMethod(origin, sym) && 1.53 + (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; 1.54 + } 1.55 + }; 1.56 + 1.57 + // <editor-fold defaultstate="collapsed" desc="isMarker"> 1.58 + 1.59 + /** 1.60 + * A cache that keeps track of marker interfaces 1.61 + */ 1.62 + class MarkerCache { 1.63 + 1.64 + private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<TypeSymbol, Entry>(); 1.65 + 1.66 + class Entry { 1.67 + final boolean isMarkerIntf; 1.68 + final int prevMark; 1.69 + 1.70 + public Entry(boolean isMarkerIntf, 1.71 + int prevMark) { 1.72 + this.isMarkerIntf = isMarkerIntf; 1.73 + this.prevMark = prevMark; 1.74 + } 1.75 + 1.76 + boolean matches(int mark) { 1.77 + return this.prevMark == mark; 1.78 + } 1.79 + } 1.80 + 1.81 + boolean get(TypeSymbol origin) throws FunctionDescriptorLookupError { 1.82 + Entry e = _map.get(origin); 1.83 + CompoundScope members = membersClosure(origin.type, false); 1.84 + if (e == null || 1.85 + !e.matches(members.getMark())) { 1.86 + boolean isMarkerIntf = isMarkerInterfaceInternal(origin, members); 1.87 + _map.put(origin, new Entry(isMarkerIntf, members.getMark())); 1.88 + return isMarkerIntf; 1.89 + } 1.90 + else { 1.91 + return e.isMarkerIntf; 1.92 + } 1.93 + } 1.94 + 1.95 + /** 1.96 + * Is given symbol a marker interface 1.97 + */ 1.98 + public boolean isMarkerInterfaceInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError { 1.99 + return !origin.isInterface() ? 1.100 + false : 1.101 + !membersCache.getElements(new DescriptorFilter(origin)).iterator().hasNext(); 1.102 + } 1.103 + } 1.104 + 1.105 + private MarkerCache markerCache = new MarkerCache(); 1.106 + 1.107 + /** 1.108 + * Is given type a marker interface? 1.109 + */ 1.110 + public boolean isMarkerInterface(Type site) { 1.111 + return markerCache.get(site.tsym); 1.112 + } 1.113 + // </editor-fold> 1.114 + 1.115 // <editor-fold defaultstate="collapsed" desc="isSubtype"> 1.116 /** 1.117 * Is t an unchecked subtype of s? 1.118 @@ -1955,45 +2012,28 @@ 1.119 * @param supertype is objectType if all bounds are interfaces, 1.120 * null otherwise. 1.121 */ 1.122 - public Type makeCompoundType(List<Type> bounds, 1.123 - Type supertype) { 1.124 + public Type makeCompoundType(List<Type> bounds) { 1.125 + return makeCompoundType(bounds, bounds.head.tsym.isInterface()); 1.126 + } 1.127 + public Type makeCompoundType(List<Type> bounds, boolean allInterfaces) { 1.128 + Assert.check(bounds.nonEmpty()); 1.129 + Type firstExplicitBound = bounds.head; 1.130 + if (allInterfaces) { 1.131 + bounds = bounds.prepend(syms.objectType); 1.132 + } 1.133 ClassSymbol bc = 1.134 new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC, 1.135 Type.moreInfo 1.136 ? names.fromString(bounds.toString()) 1.137 : names.empty, 1.138 + null, 1.139 syms.noSymbol); 1.140 - if (bounds.head.tag == TYPEVAR) 1.141 - // error condition, recover 1.142 - bc.erasure_field = syms.objectType; 1.143 - else 1.144 - bc.erasure_field = erasure(bounds.head); 1.145 - bc.members_field = new Scope(bc); 1.146 - ClassType bt = (ClassType)bc.type; 1.147 - bt.allparams_field = List.nil(); 1.148 - if (supertype != null) { 1.149 - bt.supertype_field = supertype; 1.150 - bt.interfaces_field = bounds; 1.151 - } else { 1.152 - bt.supertype_field = bounds.head; 1.153 - bt.interfaces_field = bounds.tail; 1.154 - } 1.155 - Assert.check(bt.supertype_field.tsym.completer != null 1.156 - || !bt.supertype_field.isInterface(), 1.157 - bt.supertype_field); 1.158 - return bt; 1.159 - } 1.160 - 1.161 - /** 1.162 - * Same as {@link #makeCompoundType(List,Type)}, except that the 1.163 - * second parameter is computed directly. Note that this might 1.164 - * cause a symbol completion. Hence, this version of 1.165 - * makeCompoundType may not be called during a classfile read. 1.166 - */ 1.167 - public Type makeCompoundType(List<Type> bounds) { 1.168 - Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ? 1.169 - supertype(bounds.head) : null; 1.170 - return makeCompoundType(bounds, supertype); 1.171 + bc.type = new IntersectionClassType(bounds, bc, allInterfaces); 1.172 + bc.erasure_field = (bounds.head.tag == TYPEVAR) ? 1.173 + syms.objectType : // error condition, recover 1.174 + erasure(firstExplicitBound); 1.175 + bc.members_field = new Scope(bc); 1.176 + return bc.type; 1.177 } 1.178 1.179 /** 1.180 @@ -2183,12 +2223,8 @@ 1.181 * @param supertype is objectType if all bounds are interfaces, 1.182 * null otherwise. 1.183 */ 1.184 - public void setBounds(TypeVar t, List<Type> bounds, Type supertype) { 1.185 - if (bounds.tail.isEmpty()) 1.186 - t.bound = bounds.head; 1.187 - else 1.188 - t.bound = makeCompoundType(bounds, supertype); 1.189 - t.rank_field = -1; 1.190 + public void setBounds(TypeVar t, List<Type> bounds) { 1.191 + setBounds(t, bounds, bounds.head.tsym.isInterface()); 1.192 } 1.193 1.194 /** 1.195 @@ -2200,10 +2236,10 @@ 1.196 * Note that this check might cause a symbol completion. Hence, this version of 1.197 * setBounds may not be called during a classfile read. 1.198 */ 1.199 - public void setBounds(TypeVar t, List<Type> bounds) { 1.200 - Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ? 1.201 - syms.objectType : null; 1.202 - setBounds(t, bounds, supertype); 1.203 + public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) { 1.204 + t.bound = bounds.tail.isEmpty() ? 1.205 + bounds.head : 1.206 + makeCompoundType(bounds, allInterfaces); 1.207 t.rank_field = -1; 1.208 } 1.209 // </editor-fold> 1.210 @@ -2213,7 +2249,7 @@ 1.211 * Return list of bounds of the given type variable. 1.212 */ 1.213 public List<Type> getBounds(TypeVar t) { 1.214 - if (t.bound.hasTag(NONE)) 1.215 + if (t.bound.hasTag(NONE)) 1.216 return List.nil(); 1.217 else if (t.bound.isErroneous() || !t.bound.isCompound()) 1.218 return List.of(t.bound); 1.219 @@ -3312,8 +3348,7 @@ 1.220 if (arraySuperType == null) { 1.221 // JLS 10.8: all arrays implement Cloneable and Serializable. 1.222 arraySuperType = makeCompoundType(List.of(syms.serializableType, 1.223 - syms.cloneableType), 1.224 - syms.objectType); 1.225 + syms.cloneableType), true); 1.226 } 1.227 } 1.228 }