< prev index next >

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

Print this page

  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 nullCheckOuterThis;
 109     private final boolean useMatchException;
 110     private final HashMap<TypePairs, String> typePairToName;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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







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

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











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

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

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

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

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

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

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

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

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

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

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


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

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