< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page

  90     private final Log log;
  91     private final Symtab syms;
  92     private final Resolve rs;
  93     private final Operators operators;
  94     private final Check chk;
  95     private final Attr attr;
  96     private TreeMaker make;
  97     private DiagnosticPosition make_pos;
  98     private final ConstFold cfolder;
  99     private final Target target;
 100     private final TypeEnvs typeEnvs;
 101     private final Name dollarAssertionsDisabled;
 102     private final Types types;
 103     private final TransTypes transTypes;
 104     private final boolean debugLower;
 105     private final boolean disableProtectedAccessors; // experimental
 106     private final PkgInfo pkginfoOpt;
 107     private final boolean optimizeOuterThis;
 108     private final boolean useMatchException;
 109     private final HashMap<TypePairs, String> typePairToName;

 110     private int variableIndex = 0;
 111 
 112     @SuppressWarnings("this-escape")
 113     protected Lower(Context context) {
 114         context.put(lowerKey, this);
 115         names = Names.instance(context);
 116         log = Log.instance(context);
 117         syms = Symtab.instance(context);
 118         rs = Resolve.instance(context);
 119         operators = Operators.instance(context);
 120         chk = Check.instance(context);
 121         attr = Attr.instance(context);
 122         make = TreeMaker.instance(context);
 123         cfolder = ConstFold.instance(context);
 124         target = Target.instance(context);
 125         typeEnvs = TypeEnvs.instance(context);
 126         dollarAssertionsDisabled = names.
 127             fromString(target.syntheticNameChar() + "assertionsDisabled");
 128 
 129         types = Types.instance(context);
 130         transTypes = TransTypes.instance(context);
 131         Options options = Options.instance(context);
 132         debugLower = options.isSet("debuglower");
 133         pkginfoOpt = PkgInfo.get(options);
 134         optimizeOuterThis =
 135             target.optimizeOuterThis() ||
 136             options.getBoolean("optimizeOuterThis", false);
 137         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 138         Source source = Source.instance(context);
 139         Preview preview = Preview.instance(context);
 140         useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
 141                             (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
 142         typePairToName = TypePairs.initialize(syms);


 143     }
 144 
 145     /** The currently enclosing class.
 146      */
 147     ClassSymbol currentClass;
 148 
 149     /** A queue of all translated classes.
 150      */
 151     ListBuffer<JCTree> translated;
 152 
 153     /** Environment for symbol lookup, set by translateTopLevelClass.
 154      */
 155     Env<AttrContext> attrEnv;
 156 
 157     /** A hash table mapping syntax trees to their ending source positions.
 158      */
 159     EndPosTable endPosTable;
 160 
 161 /* ************************************************************************
 162  * Global mappings

 179      * The current expected return type.
 180      */
 181     Type currentRestype;
 182 
 183     /** The current method definition.
 184      */
 185     JCMethodDecl currentMethodDef;
 186 
 187     /** The current method symbol.
 188      */
 189     MethodSymbol currentMethodSym;
 190 
 191     /** The currently enclosing outermost class definition.
 192      */
 193     JCClassDecl outermostClassDef;
 194 
 195     /** The currently enclosing outermost member definition.
 196      */
 197     JCTree outermostMemberDef;
 198 




 199     /** A navigator class for assembling a mapping from local class symbols
 200      *  to class definition trees.
 201      *  There is only one case; all other cases simply traverse down the tree.
 202      */
 203     class ClassMap extends TreeScanner {
 204 
 205         /** All encountered class defs are entered into classdefs table.
 206          */
 207         public void visitClassDef(JCClassDecl tree) {
 208             classdefs.put(tree.sym, tree);
 209             super.visitClassDef(tree);
 210         }
 211     }
 212     ClassMap classMap = new ClassMap();
 213 
 214     /** Map a class symbol to its definition.
 215      *  @param c    The class symbol of which we want to determine the definition.
 216      */
 217     JCClassDecl classDef(ClassSymbol c) {
 218         // First lookup the class in the classdefs table.

 851 
 852     /** Look up a method in a given scope.
 853      */
 854     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 855         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 856     }
 857 
 858     /** Anon inner classes are used as access constructor tags.
 859      * accessConstructorTag will use an existing anon class if one is available,
 860      * and synthesize a class (with makeEmptyClass) if one is not available.
 861      * However, there is a small possibility that an existing class will not
 862      * be generated as expected if it is inside a conditional with a constant
 863      * expression. If that is found to be the case, create an empty class tree here.
 864      */
 865     private void checkAccessConstructorTags() {
 866         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 867             ClassSymbol c = l.head;
 868             if (isTranslatedClassAvailable(c))
 869                 continue;
 870             // Create class definition tree.
 871             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,

 872                     c.outermostClass(), c.flatname, false);
 873             swapAccessConstructorTag(c, cdec.sym);
 874             translated.append(cdec);
 875         }
 876     }
 877     // where
 878     private boolean isTranslatedClassAvailable(ClassSymbol c) {
 879         for (JCTree tree: translated) {
 880             if (tree.hasTag(CLASSDEF)
 881                     && ((JCClassDecl) tree).sym == c) {
 882                 return true;
 883             }
 884         }
 885         return false;
 886     }
 887 
 888     void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
 889         for (MethodSymbol methodSymbol : accessConstrs.values()) {
 890             Assert.check(methodSymbol.type.hasTag(METHOD));
 891             MethodType oldMethodType =

1323                 accessConstrs.put(constr, aconstr);
1324                 accessed.append(constr);
1325             }
1326             return aconstr;
1327         } else {
1328             return constr;
1329         }
1330     }
1331 
1332     /** Return an anonymous class nested in this toplevel class.
1333      */
1334     ClassSymbol accessConstructorTag() {
1335         ClassSymbol topClass = currentClass.outermostClass();
1336         ModuleSymbol topModle = topClass.packge().modle;
1337         for (int i = 1; ; i++) {
1338             Name flatname = names.fromString("" + topClass.getQualifiedName() +
1339                                             target.syntheticNameChar() +
1340                                             i);
1341             ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1342             if (ctag == null)
1343                 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;

1344             else if (!ctag.isAnonymous())
1345                 continue;
1346             // keep a record of all tags, to verify that all are generated as required
1347             accessConstrTags = accessConstrTags.prepend(ctag);
1348             return ctag;
1349         }
1350     }
1351 
1352     /** Add all required access methods for a private symbol to enclosing class.
1353      *  @param sym       The symbol.
1354      */
1355     void makeAccessible(Symbol sym) {
1356         JCClassDecl cdef = classDef(sym.owner.enclClass());
1357         if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1358         if (sym.name == names.init) {
1359             cdef.defs = cdef.defs.prepend(
1360                 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1361         } else {
1362             MethodSymbol[] accessors = accessSyms.get(sym);
1363             for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {

1479 
1480     /** A stack containing the this$n field of the currently translated
1481      *  classes (if needed) in innermost first order.
1482      *  Inside a constructor, proxies and any this$n symbol are duplicated
1483      *  in an additional innermost scope, where they represent the constructor
1484      *  parameters.
1485      */
1486     List<VarSymbol> outerThisStack;
1487 
1488     /** The name of a free variable proxy.
1489      */
1490     Name proxyName(Name name, int index) {
1491         Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1492         if (index > 0) {
1493             proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1494         }
1495         return proxyName;
1496     }
1497 
1498     /** Proxy definitions for all free variables in given list, in reverse order.
1499      *  @param pos        The source code position of the definition.
1500      *  @param freevars   The free variables.
1501      *  @param owner      The class in which the definitions go.

1502      */
1503     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1504         return freevarDefs(pos, freevars, owner, 0);
1505     }
1506 
1507     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1508             long additionalFlags) {
1509         long flags = FINAL | SYNTHETIC | additionalFlags;
1510         List<JCVariableDecl> defs = List.nil();
1511         Set<Name> proxyNames = new HashSet<>();
1512         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1513             VarSymbol v = l.head;
1514             int index = 0;
1515             Name proxyName;
1516             do {
1517                 proxyName = proxyName(v.name, index++);
1518             } while (!proxyNames.add(proxyName));
1519             VarSymbol proxy = new VarSymbol(
1520                 flags, proxyName, v.erasure(types), owner);
1521             proxies.put(v, proxy);
1522             JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1523             vd.vartype = access(vd.vartype);
1524             defs = defs.prepend(vd);
1525         }
1526         return defs;

1567     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1568         ClassSymbol c = owner.enclClass();
1569         boolean isMandated =
1570             // Anonymous constructors
1571             (owner.isConstructor() && owner.isAnonymous()) ||
1572             // Constructors of non-private inner member classes
1573             (owner.isConstructor() && c.isInner() &&
1574              !c.isPrivate() && !c.isStatic());
1575         long flags =
1576             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1577         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1578         owner.extraParams = owner.extraParams.prepend(outerThis);
1579         return makeOuterThisVarDecl(pos, outerThis);
1580     }
1581 
1582     /** Definition for this$n field.
1583      *  @param pos        The source code position of the definition.
1584      *  @param owner      The class in which the definition goes.
1585      */
1586     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1587         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1588         return makeOuterThisVarDecl(pos, outerThis);
1589     }
1590 
1591     /** Return a list of trees that load the free variables in given list,
1592      *  in reverse order.
1593      *  @param pos          The source code position to be used for the trees.
1594      *  @param freevars     The list of free variables.
1595      */
1596     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1597         List<JCExpression> args = List.nil();
1598         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1599             args = args.prepend(loadFreevar(pos, l.head));
1600         return args;
1601     }
1602 //where
1603         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1604             return access(v, make.at(pos).Ident(v), null, false);
1605         }
1606 
1607     /** Construct a tree simulating the expression {@code C.this}.

1898     }
1899 
1900 /* ************************************************************************
1901  * Code for .class
1902  *************************************************************************/
1903 
1904     /** Return the symbol of a class to contain a cache of
1905      *  compiler-generated statics such as class$ and the
1906      *  $assertionsDisabled flag.  We create an anonymous nested class
1907      *  (unless one already exists) and return its symbol.  However,
1908      *  for backward compatibility in 1.4 and earlier we use the
1909      *  top-level class itself.
1910      */
1911     private ClassSymbol outerCacheClass() {
1912         ClassSymbol clazz = outermostClassDef.sym;
1913         Scope s = clazz.members();
1914         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1915             if (sym.kind == TYP &&
1916                 sym.name == names.empty &&
1917                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1918         return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;

1919     }
1920 
1921     /** Create an attributed tree of the form left.name(). */
1922     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1923         Assert.checkNonNull(left.type);
1924         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1925                                       TreeInfo.types(args));
1926         return make.App(make.Select(left, funcsym), args);
1927     }
1928 
1929     /** The tree simulating a T.class expression.
1930      *  @param clazz      The tree identifying type T.
1931      */
1932     private JCExpression classOf(JCTree clazz) {
1933         return classOfType(clazz.type, clazz.pos());
1934     }
1935 
1936     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1937         switch (type.getTag()) {
1938         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1950                 VarSymbol sym = new VarSymbol(
1951                         STATIC | PUBLIC | FINAL, names._class,
1952                         syms.classType, type.tsym);
1953                 return make_at(pos).Select(make.Type(type), sym);
1954         default:
1955             throw new AssertionError();
1956         }
1957     }
1958 
1959 /* ************************************************************************
1960  * Code for enabling/disabling assertions.
1961  *************************************************************************/
1962 
1963     private ClassSymbol assertionsDisabledClassCache;
1964 
1965     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1966      */
1967     private ClassSymbol assertionsDisabledClass() {
1968         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1969 
1970         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;

1971 
1972         return assertionsDisabledClassCache;
1973     }
1974 
1975     // This code is not particularly robust if the user has
1976     // previously declared a member named '$assertionsDisabled'.
1977     // The same faulty idiom also appears in the translation of
1978     // class literals above.  We should report an error if a
1979     // previous declaration is not synthetic.
1980 
1981     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1982         // Outermost class may be either true class or an interface.
1983         ClassSymbol outermostClass = outermostClassDef.sym;
1984 
1985         //only classes can hold a non-public field, look for a usable one:
1986         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1987                 assertionsDisabledClass();
1988 
1989         VarSymbol assertDisabledSym =
1990             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

2238         proxies = new HashMap<>(proxies);
2239         List<VarSymbol> prevOuterThisStack = outerThisStack;
2240 
2241         // If this is an enum definition
2242         if ((tree.mods.flags & ENUM) != 0 &&
2243             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2244             visitEnumDef(tree);
2245 
2246         if ((tree.mods.flags & RECORD) != 0) {
2247             visitRecordDef(tree);
2248         }
2249 
2250         // If this is a nested class, define a this$n field for
2251         // it and add to proxies.
2252         JCVariableDecl otdef = null;
2253         if (currentClass.hasOuterInstance())
2254             otdef = outerThisDef(tree.pos, currentClass);
2255 
2256         // If this is a local class, define proxies for all its free variables.
2257         List<JCVariableDecl> fvdefs = freevarDefs(
2258             tree.pos, freevars(currentClass), currentClass);
2259 
2260         // Recursively translate superclass, interfaces.
2261         tree.extending = translate(tree.extending);
2262         tree.implementing = translate(tree.implementing);
2263 
2264         if (currentClass.isDirectlyOrIndirectlyLocal()) {
2265             ClassSymbol encl = currentClass.owner.enclClass();
2266             if (encl.trans_local == null) {
2267                 encl.trans_local = List.nil();
2268             }
2269             encl.trans_local = encl.trans_local.prepend(currentClass);
2270         }
2271 
2272         // Recursively translate members, taking into account that new members
2273         // might be created during the translation and prepended to the member
2274         // list `tree.defs'.
2275         List<JCTree> seen = List.nil();
2276         while (tree.defs != seen) {
2277             List<JCTree> unseen = tree.defs;
2278             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {

2812             if (added.nonEmpty()) {
2813                 List<JCStatement> initializers = added.toList();
2814                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2815             }
2816 
2817             // pop local variables from proxy stack
2818             proxies = prevProxies;
2819 
2820             outerThisStack = prevOuterThisStack;
2821         } else {
2822             super.visitMethodDef(tree);
2823         }
2824         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2825                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2826             // lets find out if there is any field waiting to be initialized
2827             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2828             for (Symbol sym : currentClass.getEnclosedElements()) {
2829                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2830                     fields.append((VarSymbol) sym);
2831             }

2832             for (VarSymbol field: fields) {
2833                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2834                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2835                     make.at(tree.pos);
2836                     tree.body.stats = tree.body.stats.append(
2837                             make.Exec(
2838                                     make.Assign(
2839                                             make.Select(make.This(field.owner.erasure(types)), field),
2840                                             make.Ident(param)).setType(field.erasure(types))));
2841                     // we don't need the flag at the field anymore
2842                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2843                 }
2844             }







2845         }
2846         result = tree;
2847     }
2848 
2849     public void visitTypeCast(JCTypeCast tree) {
2850         tree.clazz = translate(tree.clazz);
2851         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2852             tree.expr = translate(tree.expr, tree.type);
2853         else
2854             tree.expr = translate(tree.expr);
2855         result = tree;
2856     }
2857 
2858     /**
2859      * All the exactness checks between primitive types that require a run-time
2860      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2861      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2862      * {@code S} and {@code T} are primitive types and correspond to the runtime
2863      * action that will be executed to check whether a certain value (that is passed
2864      * as a parameter) can be converted to {@code T} without loss of information.

3040         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
3041         if (constructor != tree.constructor) {
3042             tree.args = tree.args.append(makeNull());
3043             tree.constructor = constructor;
3044         }
3045 
3046         // If created class has an outer instance, and new is qualified, pass
3047         // qualifier as first argument. If new is not qualified, pass the
3048         // correct outer instance as first argument.
3049         if (c.hasOuterInstance()) {
3050             JCExpression thisArg;
3051             if (tree.encl != null) {
3052                 thisArg = attr.makeNullCheck(translate(tree.encl));
3053                 thisArg.type = tree.encl.type;
3054             } else if (c.isDirectlyOrIndirectlyLocal()) {
3055                 // local class
3056                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
3057             } else {
3058                 // nested class
3059                 thisArg = makeOwnerThis(tree.pos(), c, false);











3060             }
3061             tree.args = tree.args.prepend(thisArg);
3062         }
3063         tree.encl = null;
3064 
3065         // If we have an anonymous class, create its flat version, rather
3066         // than the class or interface following new.
3067         if (tree.def != null) {
3068             translate(tree.def);
3069 
3070             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3071             tree.def = null;
3072         } else {
3073             tree.clazz = access(c, tree.clazz, enclOp, false);
3074         }
3075         result = tree;
3076     }
3077 
3078     // Simplify conditionals with known constant controlling expressions.
3079     // This allows us to avoid generating supporting declarations for

  90     private final Log log;
  91     private final Symtab syms;
  92     private final Resolve rs;
  93     private final Operators operators;
  94     private final Check chk;
  95     private final Attr attr;
  96     private TreeMaker make;
  97     private DiagnosticPosition make_pos;
  98     private final ConstFold cfolder;
  99     private final Target target;
 100     private final TypeEnvs typeEnvs;
 101     private final Name dollarAssertionsDisabled;
 102     private final Types types;
 103     private final TransTypes transTypes;
 104     private final boolean debugLower;
 105     private final boolean disableProtectedAccessors; // experimental
 106     private final PkgInfo pkginfoOpt;
 107     private final boolean optimizeOuterThis;
 108     private final boolean useMatchException;
 109     private final HashMap<TypePairs, String> typePairToName;
 110     private final boolean allowValueClasses;
 111     private int variableIndex = 0;
 112 
 113     @SuppressWarnings("this-escape")
 114     protected Lower(Context context) {
 115         context.put(lowerKey, this);
 116         names = Names.instance(context);
 117         log = Log.instance(context);
 118         syms = Symtab.instance(context);
 119         rs = Resolve.instance(context);
 120         operators = Operators.instance(context);
 121         chk = Check.instance(context);
 122         attr = Attr.instance(context);
 123         make = TreeMaker.instance(context);
 124         cfolder = ConstFold.instance(context);
 125         target = Target.instance(context);
 126         typeEnvs = TypeEnvs.instance(context);
 127         dollarAssertionsDisabled = names.
 128             fromString(target.syntheticNameChar() + "assertionsDisabled");
 129 
 130         types = Types.instance(context);
 131         transTypes = TransTypes.instance(context);
 132         Options options = Options.instance(context);
 133         debugLower = options.isSet("debuglower");
 134         pkginfoOpt = PkgInfo.get(options);
 135         optimizeOuterThis =
 136             target.optimizeOuterThis() ||
 137             options.getBoolean("optimizeOuterThis", false);
 138         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 139         Source source = Source.instance(context);
 140         Preview preview = Preview.instance(context);
 141         useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
 142                             (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
 143         typePairToName = TypePairs.initialize(syms);
 144         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 145                 Feature.VALUE_CLASSES.allowedInSource(source);
 146     }
 147 
 148     /** The currently enclosing class.
 149      */
 150     ClassSymbol currentClass;
 151 
 152     /** A queue of all translated classes.
 153      */
 154     ListBuffer<JCTree> translated;
 155 
 156     /** Environment for symbol lookup, set by translateTopLevelClass.
 157      */
 158     Env<AttrContext> attrEnv;
 159 
 160     /** A hash table mapping syntax trees to their ending source positions.
 161      */
 162     EndPosTable endPosTable;
 163 
 164 /* ************************************************************************
 165  * Global mappings

 182      * The current expected return type.
 183      */
 184     Type currentRestype;
 185 
 186     /** The current method definition.
 187      */
 188     JCMethodDecl currentMethodDef;
 189 
 190     /** The current method symbol.
 191      */
 192     MethodSymbol currentMethodSym;
 193 
 194     /** The currently enclosing outermost class definition.
 195      */
 196     JCClassDecl outermostClassDef;
 197 
 198     /** The currently enclosing outermost member definition.
 199      */
 200     JCTree outermostMemberDef;
 201 
 202     /** A hash table mapping local classes to a set of outer this fields
 203      */
 204     public Map<ClassSymbol, Set<JCExpression>> initializerOuterThis = new WeakHashMap<>();
 205 
 206     /** A navigator class for assembling a mapping from local class symbols
 207      *  to class definition trees.
 208      *  There is only one case; all other cases simply traverse down the tree.
 209      */
 210     class ClassMap extends TreeScanner {
 211 
 212         /** All encountered class defs are entered into classdefs table.
 213          */
 214         public void visitClassDef(JCClassDecl tree) {
 215             classdefs.put(tree.sym, tree);
 216             super.visitClassDef(tree);
 217         }
 218     }
 219     ClassMap classMap = new ClassMap();
 220 
 221     /** Map a class symbol to its definition.
 222      *  @param c    The class symbol of which we want to determine the definition.
 223      */
 224     JCClassDecl classDef(ClassSymbol c) {
 225         // First lookup the class in the classdefs table.

 858 
 859     /** Look up a method in a given scope.
 860      */
 861     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 862         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 863     }
 864 
 865     /** Anon inner classes are used as access constructor tags.
 866      * accessConstructorTag will use an existing anon class if one is available,
 867      * and synthesize a class (with makeEmptyClass) if one is not available.
 868      * However, there is a small possibility that an existing class will not
 869      * be generated as expected if it is inside a conditional with a constant
 870      * expression. If that is found to be the case, create an empty class tree here.
 871      */
 872     private void checkAccessConstructorTags() {
 873         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 874             ClassSymbol c = l.head;
 875             if (isTranslatedClassAvailable(c))
 876                 continue;
 877             // Create class definition tree.
 878             // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
 879             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
 880                     c.outermostClass(), c.flatname, false);
 881             swapAccessConstructorTag(c, cdec.sym);
 882             translated.append(cdec);
 883         }
 884     }
 885     // where
 886     private boolean isTranslatedClassAvailable(ClassSymbol c) {
 887         for (JCTree tree: translated) {
 888             if (tree.hasTag(CLASSDEF)
 889                     && ((JCClassDecl) tree).sym == c) {
 890                 return true;
 891             }
 892         }
 893         return false;
 894     }
 895 
 896     void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
 897         for (MethodSymbol methodSymbol : accessConstrs.values()) {
 898             Assert.check(methodSymbol.type.hasTag(METHOD));
 899             MethodType oldMethodType =

1331                 accessConstrs.put(constr, aconstr);
1332                 accessed.append(constr);
1333             }
1334             return aconstr;
1335         } else {
1336             return constr;
1337         }
1338     }
1339 
1340     /** Return an anonymous class nested in this toplevel class.
1341      */
1342     ClassSymbol accessConstructorTag() {
1343         ClassSymbol topClass = currentClass.outermostClass();
1344         ModuleSymbol topModle = topClass.packge().modle;
1345         for (int i = 1; ; i++) {
1346             Name flatname = names.fromString("" + topClass.getQualifiedName() +
1347                                             target.syntheticNameChar() +
1348                                             i);
1349             ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1350             if (ctag == null)
1351                 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1352                 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1353             else if (!ctag.isAnonymous())
1354                 continue;
1355             // keep a record of all tags, to verify that all are generated as required
1356             accessConstrTags = accessConstrTags.prepend(ctag);
1357             return ctag;
1358         }
1359     }
1360 
1361     /** Add all required access methods for a private symbol to enclosing class.
1362      *  @param sym       The symbol.
1363      */
1364     void makeAccessible(Symbol sym) {
1365         JCClassDecl cdef = classDef(sym.owner.enclClass());
1366         if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1367         if (sym.name == names.init) {
1368             cdef.defs = cdef.defs.prepend(
1369                 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1370         } else {
1371             MethodSymbol[] accessors = accessSyms.get(sym);
1372             for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {

1488 
1489     /** A stack containing the this$n field of the currently translated
1490      *  classes (if needed) in innermost first order.
1491      *  Inside a constructor, proxies and any this$n symbol are duplicated
1492      *  in an additional innermost scope, where they represent the constructor
1493      *  parameters.
1494      */
1495     List<VarSymbol> outerThisStack;
1496 
1497     /** The name of a free variable proxy.
1498      */
1499     Name proxyName(Name name, int index) {
1500         Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1501         if (index > 0) {
1502             proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1503         }
1504         return proxyName;
1505     }
1506 
1507     /** Proxy definitions for all free variables in given list, in reverse order.
1508      *  @param pos               The source code position of the definition.
1509      *  @param freevars          The free variables.
1510      *  @param owner             The class in which the definitions go.
1511      *  @param additionalFlags   Any additional flags
1512      */




1513     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1514             long additionalFlags) {
1515         long flags = FINAL | SYNTHETIC | additionalFlags;
1516         List<JCVariableDecl> defs = List.nil();
1517         Set<Name> proxyNames = new HashSet<>();
1518         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1519             VarSymbol v = l.head;
1520             int index = 0;
1521             Name proxyName;
1522             do {
1523                 proxyName = proxyName(v.name, index++);
1524             } while (!proxyNames.add(proxyName));
1525             VarSymbol proxy = new VarSymbol(
1526                 flags, proxyName, v.erasure(types), owner);
1527             proxies.put(v, proxy);
1528             JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1529             vd.vartype = access(vd.vartype);
1530             defs = defs.prepend(vd);
1531         }
1532         return defs;

1573     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1574         ClassSymbol c = owner.enclClass();
1575         boolean isMandated =
1576             // Anonymous constructors
1577             (owner.isConstructor() && owner.isAnonymous()) ||
1578             // Constructors of non-private inner member classes
1579             (owner.isConstructor() && c.isInner() &&
1580              !c.isPrivate() && !c.isStatic());
1581         long flags =
1582             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1583         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1584         owner.extraParams = owner.extraParams.prepend(outerThis);
1585         return makeOuterThisVarDecl(pos, outerThis);
1586     }
1587 
1588     /** Definition for this$n field.
1589      *  @param pos        The source code position of the definition.
1590      *  @param owner      The class in which the definition goes.
1591      */
1592     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1593         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | (allowValueClasses && owner.isValueClass() ? STRICT : 0));
1594         return makeOuterThisVarDecl(pos, outerThis);
1595     }
1596 
1597     /** Return a list of trees that load the free variables in given list,
1598      *  in reverse order.
1599      *  @param pos          The source code position to be used for the trees.
1600      *  @param freevars     The list of free variables.
1601      */
1602     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1603         List<JCExpression> args = List.nil();
1604         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1605             args = args.prepend(loadFreevar(pos, l.head));
1606         return args;
1607     }
1608 //where
1609         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1610             return access(v, make.at(pos).Ident(v), null, false);
1611         }
1612 
1613     /** Construct a tree simulating the expression {@code C.this}.

1904     }
1905 
1906 /* ************************************************************************
1907  * Code for .class
1908  *************************************************************************/
1909 
1910     /** Return the symbol of a class to contain a cache of
1911      *  compiler-generated statics such as class$ and the
1912      *  $assertionsDisabled flag.  We create an anonymous nested class
1913      *  (unless one already exists) and return its symbol.  However,
1914      *  for backward compatibility in 1.4 and earlier we use the
1915      *  top-level class itself.
1916      */
1917     private ClassSymbol outerCacheClass() {
1918         ClassSymbol clazz = outermostClassDef.sym;
1919         Scope s = clazz.members();
1920         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1921             if (sym.kind == TYP &&
1922                 sym.name == names.empty &&
1923                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1924         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1925         return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1926     }
1927 
1928     /** Create an attributed tree of the form left.name(). */
1929     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1930         Assert.checkNonNull(left.type);
1931         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1932                                       TreeInfo.types(args));
1933         return make.App(make.Select(left, funcsym), args);
1934     }
1935 
1936     /** The tree simulating a T.class expression.
1937      *  @param clazz      The tree identifying type T.
1938      */
1939     private JCExpression classOf(JCTree clazz) {
1940         return classOfType(clazz.type, clazz.pos());
1941     }
1942 
1943     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1944         switch (type.getTag()) {
1945         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1957                 VarSymbol sym = new VarSymbol(
1958                         STATIC | PUBLIC | FINAL, names._class,
1959                         syms.classType, type.tsym);
1960                 return make_at(pos).Select(make.Type(type), sym);
1961         default:
1962             throw new AssertionError();
1963         }
1964     }
1965 
1966 /* ************************************************************************
1967  * Code for enabling/disabling assertions.
1968  *************************************************************************/
1969 
1970     private ClassSymbol assertionsDisabledClassCache;
1971 
1972     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1973      */
1974     private ClassSymbol assertionsDisabledClass() {
1975         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1976 
1977         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1978         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1979 
1980         return assertionsDisabledClassCache;
1981     }
1982 
1983     // This code is not particularly robust if the user has
1984     // previously declared a member named '$assertionsDisabled'.
1985     // The same faulty idiom also appears in the translation of
1986     // class literals above.  We should report an error if a
1987     // previous declaration is not synthetic.
1988 
1989     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1990         // Outermost class may be either true class or an interface.
1991         ClassSymbol outermostClass = outermostClassDef.sym;
1992 
1993         //only classes can hold a non-public field, look for a usable one:
1994         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1995                 assertionsDisabledClass();
1996 
1997         VarSymbol assertDisabledSym =
1998             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

2246         proxies = new HashMap<>(proxies);
2247         List<VarSymbol> prevOuterThisStack = outerThisStack;
2248 
2249         // If this is an enum definition
2250         if ((tree.mods.flags & ENUM) != 0 &&
2251             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2252             visitEnumDef(tree);
2253 
2254         if ((tree.mods.flags & RECORD) != 0) {
2255             visitRecordDef(tree);
2256         }
2257 
2258         // If this is a nested class, define a this$n field for
2259         // it and add to proxies.
2260         JCVariableDecl otdef = null;
2261         if (currentClass.hasOuterInstance())
2262             otdef = outerThisDef(tree.pos, currentClass);
2263 
2264         // If this is a local class, define proxies for all its free variables.
2265         List<JCVariableDecl> fvdefs = freevarDefs(
2266             tree.pos, freevars(currentClass), currentClass, allowValueClasses && currentClass.isValueClass() ? STRICT : 0);
2267 
2268         // Recursively translate superclass, interfaces.
2269         tree.extending = translate(tree.extending);
2270         tree.implementing = translate(tree.implementing);
2271 
2272         if (currentClass.isDirectlyOrIndirectlyLocal()) {
2273             ClassSymbol encl = currentClass.owner.enclClass();
2274             if (encl.trans_local == null) {
2275                 encl.trans_local = List.nil();
2276             }
2277             encl.trans_local = encl.trans_local.prepend(currentClass);
2278         }
2279 
2280         // Recursively translate members, taking into account that new members
2281         // might be created during the translation and prepended to the member
2282         // list `tree.defs'.
2283         List<JCTree> seen = List.nil();
2284         while (tree.defs != seen) {
2285             List<JCTree> unseen = tree.defs;
2286             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {

2820             if (added.nonEmpty()) {
2821                 List<JCStatement> initializers = added.toList();
2822                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2823             }
2824 
2825             // pop local variables from proxy stack
2826             proxies = prevProxies;
2827 
2828             outerThisStack = prevOuterThisStack;
2829         } else {
2830             super.visitMethodDef(tree);
2831         }
2832         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2833                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2834             // lets find out if there is any field waiting to be initialized
2835             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2836             for (Symbol sym : currentClass.getEnclosedElements()) {
2837                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2838                     fields.append((VarSymbol) sym);
2839             }
2840             ListBuffer<JCStatement> initializers = new ListBuffer<>();
2841             for (VarSymbol field: fields) {
2842                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2843                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2844                     make.at(tree.pos);
2845                     initializers.add(make.Exec(
2846                             make.Assign(
2847                                     make.Select(make.This(field.owner.erasure(types)), field),
2848                                     make.Ident(param)).setType(field.erasure(types))));


2849                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2850                 }
2851             }
2852             if (initializers.nonEmpty()) {
2853                 if (tree.sym.owner.isValueClass()) {
2854                     TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2855                 } else {
2856                     tree.body.stats = tree.body.stats.appendList(initializers);
2857                 }
2858             }
2859         }
2860         result = tree;
2861     }
2862 
2863     public void visitTypeCast(JCTypeCast tree) {
2864         tree.clazz = translate(tree.clazz);
2865         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2866             tree.expr = translate(tree.expr, tree.type);
2867         else
2868             tree.expr = translate(tree.expr);
2869         result = tree;
2870     }
2871 
2872     /**
2873      * All the exactness checks between primitive types that require a run-time
2874      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2875      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2876      * {@code S} and {@code T} are primitive types and correspond to the runtime
2877      * action that will be executed to check whether a certain value (that is passed
2878      * as a parameter) can be converted to {@code T} without loss of information.

3054         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
3055         if (constructor != tree.constructor) {
3056             tree.args = tree.args.append(makeNull());
3057             tree.constructor = constructor;
3058         }
3059 
3060         // If created class has an outer instance, and new is qualified, pass
3061         // qualifier as first argument. If new is not qualified, pass the
3062         // correct outer instance as first argument.
3063         if (c.hasOuterInstance()) {
3064             JCExpression thisArg;
3065             if (tree.encl != null) {
3066                 thisArg = attr.makeNullCheck(translate(tree.encl));
3067                 thisArg.type = tree.encl.type;
3068             } else if (c.isDirectlyOrIndirectlyLocal()) {
3069                 // local class
3070                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
3071             } else {
3072                 // nested class
3073                 thisArg = makeOwnerThis(tree.pos(), c, false);
3074                 if (currentMethodSym != null &&
3075                         ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
3076                         currentMethodSym.owner.isValueClass()) {
3077                     // instance initializer in a value class
3078                     Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
3079                     if (outerThisSet == null) {
3080                         outerThisSet = new HashSet<>();
3081                     }
3082                     outerThisSet.add(thisArg);
3083                     initializerOuterThis.put(currentClass, outerThisSet);
3084                 }
3085             }
3086             tree.args = tree.args.prepend(thisArg);
3087         }
3088         tree.encl = null;
3089 
3090         // If we have an anonymous class, create its flat version, rather
3091         // than the class or interface following new.
3092         if (tree.def != null) {
3093             translate(tree.def);
3094 
3095             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3096             tree.def = null;
3097         } else {
3098             tree.clazz = access(c, tree.clazz, enclOp, false);
3099         }
3100         result = tree;
3101     }
3102 
3103     // Simplify conditionals with known constant controlling expressions.
3104     // This allows us to avoid generating supporting declarations for
< prev index next >