< prev index next >

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

Print this page

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

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


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

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




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

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

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

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

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

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

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

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

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

1830     }
1831 
1832     /** Create an attributed tree of the form left.name(). */
1833     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1834         Assert.checkNonNull(left.type);
1835         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1836                                       TreeInfo.types(args));
1837         return make.App(make.Select(left, funcsym), args);
1838     }
1839 
1840     /** The tree simulating a T.class expression.
1841      *  @param clazz      The tree identifying type T.
1842      */
1843     private JCExpression classOf(JCTree clazz) {
1844         return classOfType(clazz.type, clazz.pos());
1845     }
1846 
1847     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1848         switch (type.getTag()) {
1849         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1861                 VarSymbol sym = new VarSymbol(
1862                         STATIC | PUBLIC | FINAL, names._class,
1863                         syms.classType, type.tsym);
1864                 return make_at(pos).Select(make.Type(type), sym);
1865         default:
1866             throw new AssertionError();
1867         }
1868     }
1869 
1870 /* ************************************************************************
1871  * Code for enabling/disabling assertions.
1872  *************************************************************************/
1873 
1874     private ClassSymbol assertionsDisabledClassCache;
1875 
1876     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1877      */
1878     private ClassSymbol assertionsDisabledClass() {
1879         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1880 
1881         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;

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

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

2723             if (added.nonEmpty()) {
2724                 List<JCStatement> initializers = added.toList();
2725                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2726             }
2727 
2728             // pop local variables from proxy stack
2729             proxies = prevProxies;
2730 
2731             outerThisStack = prevOuterThisStack;
2732         } else {
2733             super.visitMethodDef(tree);
2734         }
2735         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2736                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2737             // lets find out if there is any field waiting to be initialized
2738             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2739             for (Symbol sym : currentClass.getEnclosedElements()) {
2740                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2741                     fields.append((VarSymbol) sym);
2742             }

2743             for (VarSymbol field: fields) {
2744                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2745                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2746                     make.at(tree.pos);
2747                     tree.body.stats = tree.body.stats.append(
2748                             make.Exec(
2749                                     make.Assign(
2750                                             make.Select(make.This(field.owner.erasure(types)), field),
2751                                             make.Ident(param)).setType(field.erasure(types))));
2752                     // we don't need the flag at the field anymore
2753                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2754                 }
2755             }







2756         }
2757         result = tree;
2758     }
2759 
2760     public void visitTypeCast(JCTypeCast tree) {
2761         tree.clazz = translate(tree.clazz);
2762         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2763             tree.expr = translate(tree.expr, tree.type);
2764         else
2765             tree.expr = translate(tree.expr);
2766         result = tree;
2767     }
2768 
2769     /**
2770      * All the exactness checks between primitive types that require a run-time
2771      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2772      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2773      * {@code S} and {@code T} are primitive types and correspond to the runtime
2774      * action that will be executed to check whether a certain value (that is passed
2775      * as a parameter) can be converted to {@code T} without loss of information.

2951         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2952         if (constructor != tree.constructor) {
2953             tree.args = tree.args.append(makeNull());
2954             tree.constructor = constructor;
2955         }
2956 
2957         // If created class has an outer instance, and new is qualified, pass
2958         // qualifier as first argument. If new is not qualified, pass the
2959         // correct outer instance as first argument.
2960         if (c.hasOuterInstance()) {
2961             JCExpression thisArg;
2962             if (tree.encl != null) {
2963                 thisArg = attr.makeNullCheck(translate(tree.encl));
2964                 thisArg.type = tree.encl.type;
2965             } else if (c.isDirectlyOrIndirectlyLocal()) {
2966                 // local class
2967                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2968             } else {
2969                 // nested class
2970                 thisArg = makeOwnerThis(tree.pos(), c, false);











2971             }
2972             tree.args = tree.args.prepend(thisArg);
2973         }
2974         tree.encl = null;
2975 
2976         // If we have an anonymous class, create its flat version, rather
2977         // than the class or interface following new.
2978         if (tree.def != null) {
2979             translate(tree.def);
2980 
2981             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
2982             tree.def = null;
2983         } else {
2984             tree.clazz = access(c, tree.clazz, enclOp, false);
2985         }
2986         result = tree;
2987     }
2988 
2989     // Simplify conditionals with known constant controlling expressions.
2990     // This allows us to avoid generating supporting declarations for

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

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

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

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

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

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

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

2735             if (added.nonEmpty()) {
2736                 List<JCStatement> initializers = added.toList();
2737                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2738             }
2739 
2740             // pop local variables from proxy stack
2741             proxies = prevProxies;
2742 
2743             outerThisStack = prevOuterThisStack;
2744         } else {
2745             super.visitMethodDef(tree);
2746         }
2747         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2748                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2749             // lets find out if there is any field waiting to be initialized
2750             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2751             for (Symbol sym : currentClass.getEnclosedElements()) {
2752                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2753                     fields.append((VarSymbol) sym);
2754             }
2755             ListBuffer<JCStatement> initializers = new ListBuffer<>();
2756             for (VarSymbol field: fields) {
2757                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2758                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2759                     make.at(tree.pos);
2760                     initializers.add(make.Exec(
2761                             make.Assign(
2762                                     make.Select(make.This(field.owner.erasure(types)), field),
2763                                     make.Ident(param)).setType(field.erasure(types))));


2764                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2765                 }
2766             }
2767             if (initializers.nonEmpty()) {
2768                 if (tree.sym.owner.isValueClass()) {
2769                     TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2770                 } else {
2771                     tree.body.stats = tree.body.stats.appendList(initializers);
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.

2969         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2970         if (constructor != tree.constructor) {
2971             tree.args = tree.args.append(makeNull());
2972             tree.constructor = constructor;
2973         }
2974 
2975         // If created class has an outer instance, and new is qualified, pass
2976         // qualifier as first argument. If new is not qualified, pass the
2977         // correct outer instance as first argument.
2978         if (c.hasOuterInstance()) {
2979             JCExpression thisArg;
2980             if (tree.encl != null) {
2981                 thisArg = attr.makeNullCheck(translate(tree.encl));
2982                 thisArg.type = tree.encl.type;
2983             } else if (c.isDirectlyOrIndirectlyLocal()) {
2984                 // local class
2985                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2986             } else {
2987                 // nested class
2988                 thisArg = makeOwnerThis(tree.pos(), c, false);
2989                 if (currentMethodSym != null &&
2990                         ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
2991                         currentMethodSym.owner.isValueClass()) {
2992                     // instance initializer in a value class
2993                     Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
2994                     if (outerThisSet == null) {
2995                         outerThisSet = new HashSet<>();
2996                     }
2997                     outerThisSet.add(thisArg);
2998                     initializerOuterThis.put(currentClass, outerThisSet);
2999                 }
3000             }
3001             tree.args = tree.args.prepend(thisArg);
3002         }
3003         tree.encl = null;
3004 
3005         // If we have an anonymous class, create its flat version, rather
3006         // than the class or interface following new.
3007         if (tree.def != null) {
3008             translate(tree.def);
3009 
3010             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3011             tree.def = null;
3012         } else {
3013             tree.clazz = access(c, tree.clazz, enclOp, false);
3014         }
3015         result = tree;
3016     }
3017 
3018     // Simplify conditionals with known constant controlling expressions.
3019     // This allows us to avoid generating supporting declarations for
< prev index next >