< prev index next >

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

Print this page

  90     private final Symtab syms;
  91     private final Resolve rs;
  92     private final Operators operators;
  93     private final Check chk;
  94     private final Attr attr;
  95     private TreeMaker make;
  96     private DiagnosticPosition make_pos;
  97     private final ConstFold cfolder;
  98     private final Target target;
  99     private final TypeEnvs typeEnvs;
 100     private final Name dollarAssertionsDisabled;
 101     private final Types types;
 102     private final TransTypes transTypes;
 103     private final boolean debugLower;
 104     private final boolean disableProtectedAccessors; // experimental
 105     private final PkgInfo pkginfoOpt;
 106     private final boolean optimizeOuterThis;
 107     private final boolean nullCheckOuterThis;
 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         nullCheckOuterThis = options.getBoolean("nullCheckOuterThis",
 138             target.nullCheckOuterThisByDefault());
 139         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 140         Source source = Source.instance(context);
 141         Preview preview = Preview.instance(context);
 142         useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
 143                             (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
 144         typePairToName = TypePairs.initialize(syms);


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

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




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

 759 
 760     /** Look up a method in a given scope.
 761      */
 762     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 763         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 764     }
 765 
 766     /** Anon inner classes are used as access constructor tags.
 767      * accessConstructorTag will use an existing anon class if one is available,
 768      * and synthesize a class (with makeEmptyClass) if one is not available.
 769      * However, there is a small possibility that an existing class will not
 770      * be generated as expected if it is inside a conditional with a constant
 771      * expression. If that is found to be the case, create an empty class tree here.
 772      */
 773     private void checkAccessConstructorTags() {
 774         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 775             ClassSymbol c = l.head;
 776             if (isTranslatedClassAvailable(c))
 777                 continue;
 778             // Create class definition tree.
 779             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,

 780                     c.outermostClass(), c.flatname, false);
 781             swapAccessConstructorTag(c, cdec.sym);
 782             translated.append(cdec);
 783         }
 784     }
 785     // where
 786     private boolean isTranslatedClassAvailable(ClassSymbol c) {
 787         for (JCTree tree: translated) {
 788             if (tree.hasTag(CLASSDEF)
 789                     && ((JCClassDecl) tree).sym == c) {
 790                 return true;
 791             }
 792         }
 793         return false;
 794     }
 795 
 796     void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
 797         for (MethodSymbol methodSymbol : accessConstrs.values()) {
 798             Assert.check(methodSymbol.type.hasTag(METHOD));
 799             MethodType oldMethodType =

1231                 accessConstrs.put(constr, aconstr);
1232                 accessed.append(constr);
1233             }
1234             return aconstr;
1235         } else {
1236             return constr;
1237         }
1238     }
1239 
1240     /** Return an anonymous class nested in this toplevel class.
1241      */
1242     ClassSymbol accessConstructorTag() {
1243         ClassSymbol topClass = currentClass.outermostClass();
1244         ModuleSymbol topModle = topClass.packge().modle;
1245         for (int i = 1; ; i++) {
1246             Name flatname = names.fromString("" + topClass.getQualifiedName() +
1247                                             target.syntheticNameChar() +
1248                                             i);
1249             ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1250             if (ctag == null)
1251                 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;

1252             else if (!ctag.isAnonymous())
1253                 continue;
1254             // keep a record of all tags, to verify that all are generated as required
1255             accessConstrTags = accessConstrTags.prepend(ctag);
1256             return ctag;
1257         }
1258     }
1259 
1260     /** Add all required access methods for a private symbol to enclosing class.
1261      *  @param sym       The symbol.
1262      */
1263     void makeAccessible(Symbol sym) {
1264         JCClassDecl cdef = classDef(sym.owner.enclClass());
1265         if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1266         if (sym.name == names.init) {
1267             cdef.defs = cdef.defs.prepend(
1268                 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1269         } else {
1270             MethodSymbol[] accessors = accessSyms.get(sym);
1271             for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {

1387 
1388     /** A stack containing the this$n field of the currently translated
1389      *  classes (if needed) in innermost first order.
1390      *  Inside a constructor, proxies and any this$n symbol are duplicated
1391      *  in an additional innermost scope, where they represent the constructor
1392      *  parameters.
1393      */
1394     List<VarSymbol> outerThisStack;
1395 
1396     /** The name of a free variable proxy.
1397      */
1398     Name proxyName(Name name, int index) {
1399         Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1400         if (index > 0) {
1401             proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1402         }
1403         return proxyName;
1404     }
1405 
1406     /** Proxy definitions for all free variables in given list, in reverse order.
1407      *  @param pos        The source code position of the definition.
1408      *  @param freevars   The free variables.
1409      *  @param owner      The class in which the definitions go.

1410      */
1411     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1412         return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1413     }
1414 
1415     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1416             long additionalFlags) {
1417         long flags = FINAL | SYNTHETIC | additionalFlags;
1418         List<JCVariableDecl> defs = List.nil();
1419         Set<Name> proxyNames = new HashSet<>();
1420         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1421             VarSymbol v = l.head;
1422             int index = 0;
1423             Name proxyName;
1424             do {
1425                 proxyName = proxyName(v.name, index++);
1426             } while (!proxyNames.add(proxyName));
1427             VarSymbol proxy = new VarSymbol(
1428                 flags, proxyName, v.erasure(types), owner) {
1429                 @Override

1480     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1481         ClassSymbol c = owner.enclClass();
1482         boolean isMandated =
1483             // Anonymous constructors
1484             (owner.isConstructor() && owner.isAnonymous()) ||
1485             // Constructors of non-private inner member classes
1486             (owner.isConstructor() && c.isInner() &&
1487              !c.isPrivate() && !c.isStatic());
1488         long flags =
1489             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1490         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1491         owner.extraParams = owner.extraParams.prepend(outerThis);
1492         return makeOuterThisVarDecl(pos, outerThis);
1493     }
1494 
1495     /** Definition for this$n field.
1496      *  @param pos        The source code position of the definition.
1497      *  @param owner      The class in which the definition goes.
1498      */
1499     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1500         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1501         return makeOuterThisVarDecl(pos, outerThis);
1502     }
1503 
1504     /** Return a list of trees that load the free variables in given list,
1505      *  in reverse order.
1506      *  @param pos          The source code position to be used for the trees.
1507      *  @param freevars     The list of free variables.
1508      */
1509     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1510         List<JCExpression> args = List.nil();
1511         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1512             args = args.prepend(loadFreevar(pos, l.head));
1513         return args;
1514     }
1515 //where
1516         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1517             return access(v, make.at(pos).Ident(v), null, false);
1518         }
1519 
1520     /** Construct a tree simulating the expression {@code C.this}.

1820     }
1821 
1822 /* ************************************************************************
1823  * Code for .class
1824  *************************************************************************/
1825 
1826     /** Return the symbol of a class to contain a cache of
1827      *  compiler-generated statics such as class$ and the
1828      *  $assertionsDisabled flag.  We create an anonymous nested class
1829      *  (unless one already exists) and return its symbol.  However,
1830      *  for backward compatibility in 1.4 and earlier we use the
1831      *  top-level class itself.
1832      */
1833     private ClassSymbol outerCacheClass() {
1834         ClassSymbol clazz = outermostClassDef.sym;
1835         Scope s = clazz.members();
1836         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1837             if (sym.kind == TYP &&
1838                 sym.name == names.empty &&
1839                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1840         return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;

1841     }
1842 
1843     /** Create an attributed tree of the form left.name(). */
1844     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1845         Assert.checkNonNull(left.type);
1846         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1847                                       TreeInfo.types(args));
1848         return make.App(make.Select(left, funcsym), args);
1849     }
1850 
1851     /** The tree simulating a T.class expression.
1852      *  @param clazz      The tree identifying type T.
1853      */
1854     private JCExpression classOf(JCTree clazz) {
1855         return classOfType(clazz.type, clazz.pos());
1856     }
1857 
1858     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1859         switch (type.getTag()) {
1860         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1872                 VarSymbol sym = new VarSymbol(
1873                         STATIC | PUBLIC | FINAL, names._class,
1874                         syms.classType, type.tsym);
1875                 return make_at(pos).Select(make.Type(type), sym);
1876         default:
1877             throw new AssertionError();
1878         }
1879     }
1880 
1881 /* ************************************************************************
1882  * Code for enabling/disabling assertions.
1883  *************************************************************************/
1884 
1885     private ClassSymbol assertionsDisabledClassCache;
1886 
1887     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1888      */
1889     private ClassSymbol assertionsDisabledClass() {
1890         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1891 
1892         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;

1893 
1894         return assertionsDisabledClassCache;
1895     }
1896 
1897     // This code is not particularly robust if the user has
1898     // previously declared a member named '$assertionsDisabled'.
1899     // The same faulty idiom also appears in the translation of
1900     // class literals above.  We should report an error if a
1901     // previous declaration is not synthetic.
1902 
1903     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1904         // Outermost class may be either true class or an interface.
1905         ClassSymbol outermostClass = outermostClassDef.sym;
1906 
1907         //only classes can hold a non-public field, look for a usable one:
1908         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1909                 assertionsDisabledClass();
1910 
1911         VarSymbol assertDisabledSym =
1912             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

2160         proxies = new HashMap<>(proxies);
2161         List<VarSymbol> prevOuterThisStack = outerThisStack;
2162 
2163         // If this is an enum definition
2164         if ((tree.mods.flags & ENUM) != 0 &&
2165             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2166             visitEnumDef(tree);
2167 
2168         if ((tree.mods.flags & RECORD) != 0) {
2169             visitRecordDef(tree);
2170         }
2171 
2172         // If this is a nested class, define a this$n field for
2173         // it and add to proxies.
2174         JCVariableDecl otdef = null;
2175         if (currentClass.hasOuterInstance())
2176             otdef = outerThisDef(tree.pos, currentClass);
2177 
2178         // If this is a local class, define proxies for all its free variables.
2179         List<JCVariableDecl> fvdefs = freevarDefs(
2180             tree.pos, freevars(currentClass), currentClass);
2181 
2182         // Recursively translate superclass, interfaces.
2183         tree.extending = translate(tree.extending);
2184         tree.implementing = translate(tree.implementing);
2185 
2186         if (currentClass.isDirectlyOrIndirectlyLocal()) {
2187             ClassSymbol encl = currentClass.owner.enclClass();
2188             if (encl.trans_local == null) {
2189                 encl.trans_local = List.nil();
2190             }
2191             encl.trans_local = encl.trans_local.prepend(currentClass);
2192         }
2193 
2194         // Recursively translate members, taking into account that new members
2195         // might be created during the translation and prepended to the member
2196         // list `tree.defs'.
2197         List<JCTree> seen = List.nil();
2198         while (tree.defs != seen) {
2199             List<JCTree> unseen = tree.defs;
2200             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {

2741             if (added.nonEmpty()) {
2742                 List<JCStatement> initializers = added.toList();
2743                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2744             }
2745 
2746             // pop local variables from proxy stack
2747             proxies = prevProxies;
2748 
2749             outerThisStack = prevOuterThisStack;
2750         } else {
2751             super.visitMethodDef(tree);
2752         }
2753         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2754                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2755             // lets find out if there is any field waiting to be initialized
2756             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2757             for (Symbol sym : currentClass.getEnclosedElements()) {
2758                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2759                     fields.append((VarSymbol) sym);
2760             }

2761             for (VarSymbol field: fields) {
2762                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2763                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2764                     make.at(tree.pos);
2765                     tree.body.stats = tree.body.stats.append(
2766                             make.Exec(
2767                                     make.Assign(
2768                                             make.Select(make.This(field.owner.erasure(types)), field),
2769                                             make.Ident(param)).setType(field.erasure(types))));
2770                     // we don't need the flag at the field anymore
2771                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2772                 }
2773             }







2774         }
2775         result = tree;
2776     }
2777 
2778     public void visitTypeCast(JCTypeCast tree) {
2779         tree.clazz = translate(tree.clazz);
2780         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2781             tree.expr = translate(tree.expr, tree.type);
2782         else
2783             tree.expr = translate(tree.expr);
2784         result = tree;
2785     }
2786 
2787     /**
2788      * All the exactness checks between primitive types that require a run-time
2789      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2790      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2791      * {@code S} and {@code T} are primitive types and correspond to the runtime
2792      * action that will be executed to check whether a certain value (that is passed
2793      * as a parameter) can be converted to {@code T} without loss of information.

2977         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2978         if (constructor != tree.constructor) {
2979             tree.args = tree.args.append(makeNull());
2980             tree.constructor = constructor;
2981         }
2982 
2983         // If created class has an outer instance, and new is qualified, pass
2984         // qualifier as first argument. If new is not qualified, pass the
2985         // correct outer instance as first argument.
2986         if (c.hasOuterInstance()) {
2987             JCExpression thisArg;
2988             if (tree.encl != null) {
2989                 thisArg = attr.makeNullCheck(translate(tree.encl));
2990                 thisArg.type = tree.encl.type;
2991             } else if (c.isDirectlyOrIndirectlyLocal()) {
2992                 // local class
2993                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2994             } else {
2995                 // nested class
2996                 thisArg = makeOwnerThis(tree.pos(), c, false);











2997             }
2998             tree.args = tree.args.prepend(thisArg);
2999         }
3000         tree.encl = null;
3001 
3002         // If we have an anonymous class, create its flat version, rather
3003         // than the class or interface following new.
3004         if (tree.def != null) {
3005             translate(tree.def);
3006 
3007             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3008             tree.def = null;
3009         } else {
3010             tree.clazz = access(c, tree.clazz, enclOp, false);
3011         }
3012         result = tree;
3013     }
3014 
3015     // Simplify conditionals with known constant controlling expressions.
3016     // This allows us to avoid generating supporting declarations for

  90     private final Symtab syms;
  91     private final Resolve rs;
  92     private final Operators operators;
  93     private final Check chk;
  94     private final Attr attr;
  95     private TreeMaker make;
  96     private DiagnosticPosition make_pos;
  97     private final ConstFold cfolder;
  98     private final Target target;
  99     private final TypeEnvs typeEnvs;
 100     private final Name dollarAssertionsDisabled;
 101     private final Types types;
 102     private final TransTypes transTypes;
 103     private final boolean debugLower;
 104     private final boolean disableProtectedAccessors; // experimental
 105     private final PkgInfo pkginfoOpt;
 106     private final boolean optimizeOuterThis;
 107     private final boolean nullCheckOuterThis;
 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         nullCheckOuterThis = options.getBoolean("nullCheckOuterThis",
 139             target.nullCheckOuterThisByDefault());
 140         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 141         Source source = Source.instance(context);
 142         Preview preview = Preview.instance(context);
 143         useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
 144                             (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
 145         typePairToName = TypePairs.initialize(syms);
 146         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 147                 Feature.VALUE_CLASSES.allowedInSource(source);
 148     }
 149 
 150     /** The currently enclosing class.
 151      */
 152     ClassSymbol currentClass;
 153 
 154     /** A queue of all translated classes.
 155      */
 156     ListBuffer<JCTree> translated;
 157 
 158     /** Environment for symbol lookup, set by translateTopLevelClass.
 159      */
 160     Env<AttrContext> attrEnv;
 161 
 162     /** A hash table mapping syntax trees to their ending source positions.
 163      */
 164     EndPosTable endPosTable;
 165 
 166 /* ************************************************************************
 167  * Global mappings

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

 766 
 767     /** Look up a method in a given scope.
 768      */
 769     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 770         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 771     }
 772 
 773     /** Anon inner classes are used as access constructor tags.
 774      * accessConstructorTag will use an existing anon class if one is available,
 775      * and synthesize a class (with makeEmptyClass) if one is not available.
 776      * However, there is a small possibility that an existing class will not
 777      * be generated as expected if it is inside a conditional with a constant
 778      * expression. If that is found to be the case, create an empty class tree here.
 779      */
 780     private void checkAccessConstructorTags() {
 781         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 782             ClassSymbol c = l.head;
 783             if (isTranslatedClassAvailable(c))
 784                 continue;
 785             // Create class definition tree.
 786             // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
 787             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
 788                     c.outermostClass(), c.flatname, false);
 789             swapAccessConstructorTag(c, cdec.sym);
 790             translated.append(cdec);
 791         }
 792     }
 793     // where
 794     private boolean isTranslatedClassAvailable(ClassSymbol c) {
 795         for (JCTree tree: translated) {
 796             if (tree.hasTag(CLASSDEF)
 797                     && ((JCClassDecl) tree).sym == c) {
 798                 return true;
 799             }
 800         }
 801         return false;
 802     }
 803 
 804     void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
 805         for (MethodSymbol methodSymbol : accessConstrs.values()) {
 806             Assert.check(methodSymbol.type.hasTag(METHOD));
 807             MethodType oldMethodType =

1239                 accessConstrs.put(constr, aconstr);
1240                 accessed.append(constr);
1241             }
1242             return aconstr;
1243         } else {
1244             return constr;
1245         }
1246     }
1247 
1248     /** Return an anonymous class nested in this toplevel class.
1249      */
1250     ClassSymbol accessConstructorTag() {
1251         ClassSymbol topClass = currentClass.outermostClass();
1252         ModuleSymbol topModle = topClass.packge().modle;
1253         for (int i = 1; ; i++) {
1254             Name flatname = names.fromString("" + topClass.getQualifiedName() +
1255                                             target.syntheticNameChar() +
1256                                             i);
1257             ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1258             if (ctag == null)
1259                 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1260                 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1261             else if (!ctag.isAnonymous())
1262                 continue;
1263             // keep a record of all tags, to verify that all are generated as required
1264             accessConstrTags = accessConstrTags.prepend(ctag);
1265             return ctag;
1266         }
1267     }
1268 
1269     /** Add all required access methods for a private symbol to enclosing class.
1270      *  @param sym       The symbol.
1271      */
1272     void makeAccessible(Symbol sym) {
1273         JCClassDecl cdef = classDef(sym.owner.enclClass());
1274         if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1275         if (sym.name == names.init) {
1276             cdef.defs = cdef.defs.prepend(
1277                 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1278         } else {
1279             MethodSymbol[] accessors = accessSyms.get(sym);
1280             for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {

1396 
1397     /** A stack containing the this$n field of the currently translated
1398      *  classes (if needed) in innermost first order.
1399      *  Inside a constructor, proxies and any this$n symbol are duplicated
1400      *  in an additional innermost scope, where they represent the constructor
1401      *  parameters.
1402      */
1403     List<VarSymbol> outerThisStack;
1404 
1405     /** The name of a free variable proxy.
1406      */
1407     Name proxyName(Name name, int index) {
1408         Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1409         if (index > 0) {
1410             proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1411         }
1412         return proxyName;
1413     }
1414 
1415     /** Proxy definitions for all free variables in given list, in reverse order.
1416      *  @param pos               The source code position of the definition.
1417      *  @param freevars          The free variables.
1418      *  @param owner             The class in which the definitions go.
1419      *  @param additionalFlags   Any additional flags
1420      */
1421     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1422         return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1423     }
1424 
1425     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1426             long additionalFlags) {
1427         long flags = FINAL | SYNTHETIC | additionalFlags;
1428         List<JCVariableDecl> defs = List.nil();
1429         Set<Name> proxyNames = new HashSet<>();
1430         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1431             VarSymbol v = l.head;
1432             int index = 0;
1433             Name proxyName;
1434             do {
1435                 proxyName = proxyName(v.name, index++);
1436             } while (!proxyNames.add(proxyName));
1437             VarSymbol proxy = new VarSymbol(
1438                 flags, proxyName, v.erasure(types), owner) {
1439                 @Override

1490     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1491         ClassSymbol c = owner.enclClass();
1492         boolean isMandated =
1493             // Anonymous constructors
1494             (owner.isConstructor() && owner.isAnonymous()) ||
1495             // Constructors of non-private inner member classes
1496             (owner.isConstructor() && c.isInner() &&
1497              !c.isPrivate() && !c.isStatic());
1498         long flags =
1499             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1500         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1501         owner.extraParams = owner.extraParams.prepend(outerThis);
1502         return makeOuterThisVarDecl(pos, outerThis);
1503     }
1504 
1505     /** Definition for this$n field.
1506      *  @param pos        The source code position of the definition.
1507      *  @param owner      The class in which the definition goes.
1508      */
1509     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1510         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | (allowValueClasses && owner.isValueClass() ? STRICT : 0));
1511         return makeOuterThisVarDecl(pos, outerThis);
1512     }
1513 
1514     /** Return a list of trees that load the free variables in given list,
1515      *  in reverse order.
1516      *  @param pos          The source code position to be used for the trees.
1517      *  @param freevars     The list of free variables.
1518      */
1519     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1520         List<JCExpression> args = List.nil();
1521         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1522             args = args.prepend(loadFreevar(pos, l.head));
1523         return args;
1524     }
1525 //where
1526         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1527             return access(v, make.at(pos).Ident(v), null, false);
1528         }
1529 
1530     /** Construct a tree simulating the expression {@code C.this}.

1830     }
1831 
1832 /* ************************************************************************
1833  * Code for .class
1834  *************************************************************************/
1835 
1836     /** Return the symbol of a class to contain a cache of
1837      *  compiler-generated statics such as class$ and the
1838      *  $assertionsDisabled flag.  We create an anonymous nested class
1839      *  (unless one already exists) and return its symbol.  However,
1840      *  for backward compatibility in 1.4 and earlier we use the
1841      *  top-level class itself.
1842      */
1843     private ClassSymbol outerCacheClass() {
1844         ClassSymbol clazz = outermostClassDef.sym;
1845         Scope s = clazz.members();
1846         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1847             if (sym.kind == TYP &&
1848                 sym.name == names.empty &&
1849                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1850         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1851         return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1852     }
1853 
1854     /** Create an attributed tree of the form left.name(). */
1855     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1856         Assert.checkNonNull(left.type);
1857         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1858                                       TreeInfo.types(args));
1859         return make.App(make.Select(left, funcsym), args);
1860     }
1861 
1862     /** The tree simulating a T.class expression.
1863      *  @param clazz      The tree identifying type T.
1864      */
1865     private JCExpression classOf(JCTree clazz) {
1866         return classOfType(clazz.type, clazz.pos());
1867     }
1868 
1869     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1870         switch (type.getTag()) {
1871         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1883                 VarSymbol sym = new VarSymbol(
1884                         STATIC | PUBLIC | FINAL, names._class,
1885                         syms.classType, type.tsym);
1886                 return make_at(pos).Select(make.Type(type), sym);
1887         default:
1888             throw new AssertionError();
1889         }
1890     }
1891 
1892 /* ************************************************************************
1893  * Code for enabling/disabling assertions.
1894  *************************************************************************/
1895 
1896     private ClassSymbol assertionsDisabledClassCache;
1897 
1898     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1899      */
1900     private ClassSymbol assertionsDisabledClass() {
1901         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1902 
1903         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1904         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1905 
1906         return assertionsDisabledClassCache;
1907     }
1908 
1909     // This code is not particularly robust if the user has
1910     // previously declared a member named '$assertionsDisabled'.
1911     // The same faulty idiom also appears in the translation of
1912     // class literals above.  We should report an error if a
1913     // previous declaration is not synthetic.
1914 
1915     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1916         // Outermost class may be either true class or an interface.
1917         ClassSymbol outermostClass = outermostClassDef.sym;
1918 
1919         //only classes can hold a non-public field, look for a usable one:
1920         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1921                 assertionsDisabledClass();
1922 
1923         VarSymbol assertDisabledSym =
1924             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

2172         proxies = new HashMap<>(proxies);
2173         List<VarSymbol> prevOuterThisStack = outerThisStack;
2174 
2175         // If this is an enum definition
2176         if ((tree.mods.flags & ENUM) != 0 &&
2177             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2178             visitEnumDef(tree);
2179 
2180         if ((tree.mods.flags & RECORD) != 0) {
2181             visitRecordDef(tree);
2182         }
2183 
2184         // If this is a nested class, define a this$n field for
2185         // it and add to proxies.
2186         JCVariableDecl otdef = null;
2187         if (currentClass.hasOuterInstance())
2188             otdef = outerThisDef(tree.pos, currentClass);
2189 
2190         // If this is a local class, define proxies for all its free variables.
2191         List<JCVariableDecl> fvdefs = freevarDefs(
2192             tree.pos, freevars(currentClass), currentClass, allowValueClasses && currentClass.isValueClass() ? STRICT : LOCAL_CAPTURE_FIELD);
2193 
2194         // Recursively translate superclass, interfaces.
2195         tree.extending = translate(tree.extending);
2196         tree.implementing = translate(tree.implementing);
2197 
2198         if (currentClass.isDirectlyOrIndirectlyLocal()) {
2199             ClassSymbol encl = currentClass.owner.enclClass();
2200             if (encl.trans_local == null) {
2201                 encl.trans_local = List.nil();
2202             }
2203             encl.trans_local = encl.trans_local.prepend(currentClass);
2204         }
2205 
2206         // Recursively translate members, taking into account that new members
2207         // might be created during the translation and prepended to the member
2208         // list `tree.defs'.
2209         List<JCTree> seen = List.nil();
2210         while (tree.defs != seen) {
2211             List<JCTree> unseen = tree.defs;
2212             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {

2753             if (added.nonEmpty()) {
2754                 List<JCStatement> initializers = added.toList();
2755                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2756             }
2757 
2758             // pop local variables from proxy stack
2759             proxies = prevProxies;
2760 
2761             outerThisStack = prevOuterThisStack;
2762         } else {
2763             super.visitMethodDef(tree);
2764         }
2765         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2766                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2767             // lets find out if there is any field waiting to be initialized
2768             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2769             for (Symbol sym : currentClass.getEnclosedElements()) {
2770                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2771                     fields.append((VarSymbol) sym);
2772             }
2773             ListBuffer<JCStatement> initializers = new ListBuffer<>();
2774             for (VarSymbol field: fields) {
2775                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2776                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2777                     make.at(tree.pos);
2778                     initializers.add(make.Exec(
2779                             make.Assign(
2780                                     make.Select(make.This(field.owner.erasure(types)), field),
2781                                     make.Ident(param)).setType(field.erasure(types))));


2782                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2783                 }
2784             }
2785             if (initializers.nonEmpty()) {
2786                 if (allowValueClasses && (tree.sym.owner.isValueClass() || tree.sym.owner.hasStrict() || ((ClassSymbol)tree.sym.owner).isRecord())) {
2787                     TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2788                 } else {
2789                     tree.body.stats = tree.body.stats.appendList(initializers);
2790                 }
2791             }
2792         }
2793         result = tree;
2794     }
2795 
2796     public void visitTypeCast(JCTypeCast tree) {
2797         tree.clazz = translate(tree.clazz);
2798         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2799             tree.expr = translate(tree.expr, tree.type);
2800         else
2801             tree.expr = translate(tree.expr);
2802         result = tree;
2803     }
2804 
2805     /**
2806      * All the exactness checks between primitive types that require a run-time
2807      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2808      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2809      * {@code S} and {@code T} are primitive types and correspond to the runtime
2810      * action that will be executed to check whether a certain value (that is passed
2811      * as a parameter) can be converted to {@code T} without loss of information.

2995         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2996         if (constructor != tree.constructor) {
2997             tree.args = tree.args.append(makeNull());
2998             tree.constructor = constructor;
2999         }
3000 
3001         // If created class has an outer instance, and new is qualified, pass
3002         // qualifier as first argument. If new is not qualified, pass the
3003         // correct outer instance as first argument.
3004         if (c.hasOuterInstance()) {
3005             JCExpression thisArg;
3006             if (tree.encl != null) {
3007                 thisArg = attr.makeNullCheck(translate(tree.encl));
3008                 thisArg.type = tree.encl.type;
3009             } else if (c.isDirectlyOrIndirectlyLocal()) {
3010                 // local class
3011                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
3012             } else {
3013                 // nested class
3014                 thisArg = makeOwnerThis(tree.pos(), c, false);
3015                 if (currentMethodSym != null &&
3016                         ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
3017                         currentMethodSym.owner.isValueClass()) {
3018                     // instance initializer in a value class
3019                     Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
3020                     if (outerThisSet == null) {
3021                         outerThisSet = new HashSet<>();
3022                     }
3023                     outerThisSet.add(thisArg);
3024                     initializerOuterThis.put(currentClass, outerThisSet);
3025                 }
3026             }
3027             tree.args = tree.args.prepend(thisArg);
3028         }
3029         tree.encl = null;
3030 
3031         // If we have an anonymous class, create its flat version, rather
3032         // than the class or interface following new.
3033         if (tree.def != null) {
3034             translate(tree.def);
3035 
3036             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3037             tree.def = null;
3038         } else {
3039             tree.clazz = access(c, tree.clazz, enclOp, false);
3040         }
3041         result = tree;
3042     }
3043 
3044     // Simplify conditionals with known constant controlling expressions.
3045     // This allows us to avoid generating supporting declarations for
< prev index next >