src/share/classes/com/sun/tools/javac/code/Types.java

changeset 1436
f6f1fd261f57
parent 1434
34d1ebaf4645
child 1442
fcf89720ae71
     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              }

mercurial