< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java

Print this page

  46 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  47 import com.sun.tools.javac.tree.EndPosTable;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 
  50 import static com.sun.tools.javac.code.Flags.*;
  51 import static com.sun.tools.javac.code.Kinds.Kind.*;
  52 import static com.sun.tools.javac.code.TypeTag.*;
  53 import static com.sun.tools.javac.jvm.ByteCodes.*;
  54 import static com.sun.tools.javac.jvm.CRTFlags.*;
  55 import static com.sun.tools.javac.main.Option.*;
  56 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  57 
  58 /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
  59  *
  60  *  <p><b>This is NOT part of any supported API.
  61  *  If you write code that depends on this, you do so at your own risk.
  62  *  This code and its internal interfaces are subject to change or
  63  *  deletion without notice.</b>
  64  */
  65 public class Gen extends JCTree.Visitor {

  66     protected static final Context.Key<Gen> genKey = new Context.Key<>();
  67 
  68     private final Log log;
  69     private final Symtab syms;
  70     private final Check chk;
  71     private final Resolve rs;
  72     private final TreeMaker make;
  73     private final Names names;
  74     private final Target target;
  75     private final Name accessDollar;
  76     private final Types types;
  77     private final Lower lower;
  78     private final Annotate annotate;
  79     private final StringConcat concat;

  80 
  81     /** Format of stackmap tables to be generated. */
  82     private final Code.StackMapFormat stackMap;
  83 
  84     /** A type that serves as the expected type for all method expressions.
  85      */
  86     private final Type methodType;
  87 
  88     public static Gen instance(Context context) {
  89         Gen instance = context.get(genKey);
  90         if (instance == null)
  91             instance = new Gen(context);
  92         return instance;
  93     }
  94 
  95     /** Constant pool writer, set by genClass.
  96      */
  97     final PoolWriter poolWriter;
  98 
  99     protected Gen(Context context) {
 100         context.put(genKey, this);
 101 
 102         names = Names.instance(context);
 103         log = Log.instance(context);
 104         syms = Symtab.instance(context);
 105         chk = Check.instance(context);
 106         rs = Resolve.instance(context);
 107         make = TreeMaker.instance(context);
 108         target = Target.instance(context);
 109         types = Types.instance(context);
 110         concat = StringConcat.instance(context);
 111 
 112         methodType = new MethodType(null, null, null, syms.methodClass);
 113         accessDollar = names.
 114             fromString("access" + target.syntheticNameChar());
 115         lower = Lower.instance(context);

 116 
 117         Options options = Options.instance(context);
 118         lineDebugInfo =
 119             options.isUnset(G_CUSTOM) ||
 120             options.isSet(G_CUSTOM, "lines");
 121         varDebugInfo =
 122             options.isUnset(G_CUSTOM)
 123             ? options.isSet(G)
 124             : options.isSet(G_CUSTOM, "vars");
 125         genCrt = options.isSet(XJCOV);
 126         debugCode = options.isSet("debug.code");
 127         disableVirtualizedPrivateInvoke = options.isSet("disableVirtualizedPrivateInvoke");
 128         poolWriter = new PoolWriter(types, names);
 129 
 130         // ignore cldc because we cannot have both stackmap formats
 131         this.stackMap = StackMapFormat.JSR202;
 132         annotate = Annotate.instance(context);
 133         qualifiedSymbolCache = new HashMap<>();


 134     }
 135 
 136     /** Switches
 137      */
 138     private final boolean lineDebugInfo;
 139     private final boolean varDebugInfo;
 140     private final boolean genCrt;
 141     private final boolean debugCode;
 142     private boolean disableVirtualizedPrivateInvoke;
 143 
 144     /** Code buffer, set by genMethod.
 145      */
 146     private Code code;
 147 
 148     /** Items structure, set by genMethod.
 149      */
 150     private Items items;
 151 
 152     /** Environment for symbol lookup, set by genClass
 153      */

 161      */
 162     private int nerrs = 0;
 163 
 164     /** An object containing mappings of syntax trees to their
 165      *  ending source positions.
 166      */
 167     EndPosTable endPosTable;
 168 
 169     boolean inCondSwitchExpression;
 170     Chain switchExpressionTrueChain;
 171     Chain switchExpressionFalseChain;
 172     List<LocalItem> stackBeforeSwitchExpression;
 173     LocalItem switchResult;
 174 
 175     /** Cache the symbol to reflect the qualifying type.
 176      *  key: corresponding type
 177      *  value: qualified symbol
 178      */
 179     Map<Type, Symbol> qualifiedSymbolCache;
 180 


 181     /** Generate code to load an integer constant.
 182      *  @param n     The integer to be loaded.
 183      */
 184     void loadIntConst(int n) {
 185         items.makeImmediateItem(syms.intType, n).load();
 186     }
 187 
 188     /** The opcode that loads a zero constant of a given type code.
 189      *  @param tc   The given type code (@see ByteCode).
 190      */
 191     public static int zero(int tc) {
 192         switch(tc) {
 193         case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
 194             return iconst_0;
 195         case LONGcode:
 196             return lconst_0;
 197         case FLOATcode:
 198             return fconst_0;
 199         case DOUBLEcode:
 200             return dconst_0;

 244             if ((qualifier = qualifiedSymbolCache.get(site)) == null) {
 245                 qualifier = new ClassSymbol(Flags.PUBLIC, site.tsym.name, site, syms.noSymbol);
 246                 qualifiedSymbolCache.put(site, qualifier);
 247             }
 248             return sym.clone(qualifier);
 249         }
 250 
 251         if (sym.owner == site.tsym ||
 252             (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
 253             return sym;
 254         }
 255 
 256         // leave alone methods inherited from Object
 257         // JLS 13.1.
 258         if (sym.owner == syms.objectType.tsym)
 259             return sym;
 260 
 261         return sym.clone(site.tsym);
 262     }
 263 














 264     /** Insert a reference to given type in the constant pool,
 265      *  checking for an array with too many dimensions;
 266      *  return the reference's index.
 267      *  @param type   The type for which a reference is inserted.
 268      */
 269     int makeRef(DiagnosticPosition pos, Type type) {
 270         return poolWriter.putClass(checkDimension(pos, type));
 271     }
 272 
 273     /** Check if the given type is an array with too many dimensions.
 274      */
 275     private Type checkDimension(DiagnosticPosition pos, Type t) {
 276         checkDimensionInternal(pos, t);
 277         return t;
 278     }
 279 
 280     private void checkDimensionInternal(DiagnosticPosition pos, Type t) {
 281         switch (t.getTag()) {
 282         case METHOD:
 283             checkDimension(pos, t.getReturnType());
 284             for (List<Type> args = t.getParameterTypes(); args.nonEmpty(); args = args.tail)
 285                 checkDimension(pos, args.head);
 286             break;
 287         case ARRAY:
 288             if (types.dimensions(t) > ClassFile.MAX_DIMENSIONS) {
 289                 log.error(pos, Errors.LimitDimensions);
 290                 nerrs++;

 304                                     type,
 305                                     env.enclMethod.sym);
 306         code.newLocal(v);
 307         return items.makeLocalItem(v);
 308     }
 309 
 310     /** Generate code to call a non-private method or constructor.
 311      *  @param pos         Position to be used for error reporting.
 312      *  @param site        The type of which the method is a member.
 313      *  @param name        The method's name.
 314      *  @param argtypes    The method's argument types.
 315      *  @param isStatic    A flag that indicates whether we call a
 316      *                     static or instance method.
 317      */
 318     void callMethod(DiagnosticPosition pos,
 319                     Type site, Name name, List<Type> argtypes,
 320                     boolean isStatic) {
 321         Symbol msym = rs.
 322             resolveInternalMethod(pos, attrEnv, site, name, argtypes, null);
 323         if (isStatic) items.makeStaticItem(msym).invoke();
 324         else items.makeMemberItem(msym, name == names.init).invoke();
 325     }
 326 
 327     /** Is the given method definition an access method
 328      *  resulting from a qualified super? This is signified by an odd
 329      *  access code.
 330      */
 331     private boolean isAccessSuper(JCMethodDecl enclMethod) {
 332         return
 333             (enclMethod.mods.flags & SYNTHETIC) != 0 &&
 334             isOddAccessName(enclMethod.name);
 335     }
 336 
 337     /** Does given name start with "access$" and end in an odd digit?
 338      */
 339     private boolean isOddAccessName(Name name) {
 340         return
 341             name.startsWith(accessDollar) &&
 342             (name.getByteAt(name.getByteLength() - 1) & 1) == 1;
 343     }
 344 

 527     /** Check a constant value and report if it is a string that is
 528      *  too large.
 529      */
 530     private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
 531         if (nerrs != 0 || // only complain about a long string once
 532             constValue == null ||
 533             !(constValue instanceof String str) ||
 534             str.length() < PoolWriter.MAX_STRING_LENGTH)
 535             return;
 536         log.error(pos, Errors.LimitString);
 537         nerrs++;
 538     }
 539 
 540     /** Insert instance initializer code into initial constructor.
 541      *  @param md        The tree potentially representing a
 542      *                   constructor's definition.
 543      *  @param initCode  The list of instance initializer statements.
 544      *  @param initTAs  Type annotations from the initializer expression.
 545      */
 546     void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
 547         if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
 548             // We are seeing a constructor that does not call another
 549             // constructor of the same class.
 550             List<JCStatement> stats = md.body.stats;
 551             ListBuffer<JCStatement> newstats = new ListBuffer<>();
 552 
 553             if (stats.nonEmpty()) {
 554                 // Copy initializers of synthetic variables generated in
 555                 // the translation of inner classes.
 556                 while (TreeInfo.isSyntheticInit(stats.head)) {
 557                     newstats.append(stats.head);
 558                     stats = stats.tail;
 559                 }
 560                 // Copy superclass constructor call
 561                 newstats.append(stats.head);
 562                 stats = stats.tail;
 563                 // Copy remaining synthetic initializers.
 564                 while (stats.nonEmpty() &&
 565                        TreeInfo.isSyntheticInit(stats.head)) {
 566                     newstats.append(stats.head);
 567                     stats = stats.tail;

 930         // is the method's return type.
 931         this.pt = tree.sym.erasure(types).getReturnType();
 932 
 933         checkDimension(tree.pos(), tree.sym.erasure(types));
 934         genMethod(tree, localEnv, false);
 935     }
 936 //where
 937         /** Generate code for a method.
 938          *  @param tree     The tree representing the method definition.
 939          *  @param env      The environment current for the method body.
 940          *  @param fatcode  A flag that indicates whether all jumps are
 941          *                  within 32K.  We first invoke this method under
 942          *                  the assumption that fatcode == false, i.e. all
 943          *                  jumps are within 32K.  If this fails, fatcode
 944          *                  is set to true and we try again.
 945          */
 946         void genMethod(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
 947             MethodSymbol meth = tree.sym;
 948             int extras = 0;
 949             // Count up extra parameters
 950             if (meth.isConstructor()) {
 951                 extras++;
 952                 if (meth.enclClass().isInner() &&
 953                     !meth.enclClass().isStatic()) {
 954                     extras++;
 955                 }
 956             } else if ((tree.mods.flags & STATIC) == 0) {
 957                 extras++;
 958             }
 959             //      System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG
 960             if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) + extras >
 961                 ClassFile.MAX_PARAMETERS) {
 962                 log.error(tree.pos(), Errors.LimitParameters);
 963                 nerrs++;
 964             }
 965 
 966             else if (tree.body != null) {
 967                 // Create a new code structure and initialize it.
 968                 int startpcCrt = initCode(tree, env, fatcode);
 969 
 970                 try {
 971                     genStat(tree.body, env);
 972                 } catch (CodeSizeOverflow e) {
 973                     // Failed due to code limit, try again with jsr/ret
 974                     startpcCrt = initCode(tree, env, fatcode);
 975                     genStat(tree.body, env);
 976                 }
 977 
 978                 if (code.state.stacksize != 0) {
 979                     log.error(tree.body.pos(), Errors.StackSimError(tree.sym));
 980                     throw new AssertionError();
 981                 }
 982 
 983                 // If last statement could complete normally, insert a
 984                 // return at the end.
 985                 if (code.isAlive()) {
 986                     code.statBegin(TreeInfo.endPos(tree.body));
 987                     if (env.enclMethod == null ||
 988                         env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
 989                         code.emitop0(return_);



 990                     } else {
 991                         // sometime dead code seems alive (4415991);
 992                         // generate a small loop instead
 993                         int startpc = code.entryPoint();
 994                         CondItem c = items.makeCondItem(goto_);
 995                         code.resolve(c.jumpTrue(), startpc);
 996                     }
 997                 }
 998                 if (genCrt)
 999                     code.crt.put(tree.body,
1000                                  CRT_BLOCK,
1001                                  startpcCrt,
1002                                  code.curCP());
1003 
1004                 code.endScopes(0);
1005 
1006                 // If we exceeded limits, panic
1007                 if (code.checkLimits(tree.pos(), log)) {
1008                     nerrs++;
1009                     return;

1024 
1025                 // Fill in type annotation positions for exception parameters
1026                 code.fillExceptionParameterPositions();
1027             }
1028         }
1029 
1030         private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
1031             MethodSymbol meth = tree.sym;
1032 
1033             // Create a new code structure.
1034             meth.code = code = new Code(meth,
1035                                         fatcode,
1036                                         lineDebugInfo ? toplevel.lineMap : null,
1037                                         varDebugInfo,
1038                                         stackMap,
1039                                         debugCode,
1040                                         genCrt ? new CRTable(tree, env.toplevel.endPositions)
1041                                                : null,
1042                                         syms,
1043                                         types,
1044                                         poolWriter);

1045             items = new Items(poolWriter, code, syms, types);
1046             if (code.debugCode) {
1047                 System.err.println(meth + " for body " + tree);
1048             }
1049 
1050             // If method is not static, create a new local variable address
1051             // for `this'.
1052             if ((tree.mods.flags & STATIC) == 0) {
1053                 Type selfType = meth.owner.type;
1054                 if (meth.isConstructor() && selfType != syms.objectType)
1055                     selfType = UninitializedType.uninitializedThis(selfType);
1056                 code.setDefined(
1057                         code.newLocal(
1058                             new VarSymbol(FINAL, names._this, selfType, meth.owner)));
1059             }
1060 
1061             // Mark all parameters as defined from the beginning of
1062             // the method.
1063             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1064                 checkDimension(l.head.pos(), l.head.sym.type);
1065                 code.setDefined(code.newLocal(l.head.sym));
1066             }
1067 
1068             // Get ready to generate code for method body.
1069             int startpcCrt = genCrt ? code.curCP() : 0;
1070             code.entryPoint();
1071 
1072             // Suppress initial stackmap
1073             code.pendingStackMap = false;
1074 
1075             return startpcCrt;
1076         }
1077 
1078     public void visitVarDef(JCVariableDecl tree) {
1079         VarSymbol v = tree.sym;
1080         if (tree.init != null) {
1081             checkStringConstant(tree.init.pos(), v.getConstValue());
1082             if (v.getConstValue() == null || varDebugInfo) {
1083                 Assert.check(code.isStatementStart());
1084                 code.newLocal(v);
1085                 genExpr(tree.init, v.erasure(types)).load();
1086                 items.makeLocalItem(v).store();
1087                 Assert.check(code.isStatementStart());
1088             }
1089         } else {
1090             code.newLocal(v);
1091         }
1092         checkDimension(tree.pos(), v.type);




1093     }
1094 
1095     public void visitSkip(JCSkip tree) {
1096     }
1097 
1098     public void visitBlock(JCBlock tree) {
1099         int limit = code.nextreg;
1100         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1101         genStats(tree.stats, localEnv);
1102         // End the scope of all block-local variables in variable info.
1103         if (!env.tree.hasTag(METHODDEF)) {
1104             code.statBegin(tree.endpos);
1105             code.endScopes(limit);
1106             code.pendingStatPos = Position.NOPOS;
1107         }
1108     }
1109 
1110     public void visitDoLoop(JCDoWhileLoop tree) {
1111         genLoop(tree, tree.body, tree.cond, List.nil(), false);
1112     }
1113 
1114     public void visitWhileLoop(JCWhileLoop tree) {
1115         genLoop(tree, tree.body, tree.cond, List.nil(), true);
1116     }
1117 































1118     public void visitForLoop(JCForLoop tree) {
1119         int limit = code.nextreg;
1120         genStats(tree.init, env);
1121         genLoop(tree, tree.body, tree.cond, tree.step, true);
1122         code.endScopes(limit);
1123     }
1124     //where
1125         /** Generate code for a loop.
1126          *  @param loop       The tree representing the loop.
1127          *  @param body       The loop's body.
1128          *  @param cond       The loop's controlling condition.
1129          *  @param step       "Step" statements to be inserted at end of
1130          *                    each iteration.
1131          *  @param testFirst  True if the loop test belongs before the body.
1132          */
1133         private void genLoop(JCStatement loop,
1134                              JCStatement body,
1135                              JCExpression cond,
1136                              List<JCExpressionStatement> step,
1137                              boolean testFirst) {

1992             result = arr;
1993         } else {
1994             for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
1995                 genExpr(l.head, syms.intType).load();
1996             }
1997             result = makeNewArray(tree.pos(), tree.type, tree.dims.length());
1998         }
1999     }
2000 //where
2001         /** Generate code to create an array with given element type and number
2002          *  of dimensions.
2003          */
2004         Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
2005             Type elemtype = types.elemtype(type);
2006             if (types.dimensions(type) > ClassFile.MAX_DIMENSIONS) {
2007                 log.error(pos, Errors.LimitDimensions);
2008                 nerrs++;
2009             }
2010             int elemcode = Code.arraycode(elemtype);
2011             if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
2012                 code.emitAnewarray(makeRef(pos, elemtype), type);
2013             } else if (elemcode == 1) {
2014                 code.emitMultianewarray(ndims, makeRef(pos, type), type);
2015             } else {
2016                 code.emitNewarray(elemcode, type);
2017             }
2018             return items.makeStackItem(type);
2019         }
2020 
2021     public void visitParens(JCParens tree) {
2022         result = genExpr(tree.expr, tree.expr.type);
2023     }
2024 
2025     public void visitAssign(JCAssign tree) {
2026         Item l = genExpr(tree.lhs, tree.lhs.type);
2027         genExpr(tree.rhs, tree.lhs.type).load();
2028         if (tree.rhs.type.hasTag(BOT)) {
2029             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
2030                for "regarding a reference as having some other type in a manner that can be proved
2031                correct at compile time."
2032             */

2218                     code.emitop0(opcode >> preShift);
2219                     opcode = opcode & 0xFF;
2220                 }
2221             }
2222             if (opcode >= ifeq && opcode <= if_acmpne ||
2223                 opcode == if_acmp_null || opcode == if_acmp_nonnull) {
2224                 return items.makeCondItem(opcode);
2225             } else {
2226                 code.emitop0(opcode);
2227                 return items.makeStackItem(optype.restype);
2228             }
2229         }
2230 
2231     public void visitTypeCast(JCTypeCast tree) {
2232         result = genExpr(tree.expr, tree.clazz.type).load();
2233         setTypeAnnotationPositions(tree.pos);
2234         // Additional code is only needed if we cast to a reference type
2235         // which is not statically a supertype of the expression's type.
2236         // For basic types, the coerce(...) in genExpr(...) will do
2237         // the conversion.

2238         if (!tree.clazz.type.isPrimitive() &&
2239            !types.isSameType(tree.expr.type, tree.clazz.type) &&
2240            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
2241             code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);







2242         }
2243     }
2244 
2245     public void visitWildcard(JCWildcard tree) {
2246         throw new AssertionError(this.getClass().getName());
2247     }
2248 
2249     public void visitTypeTest(JCInstanceOf tree) {
2250         genExpr(tree.expr, tree.expr.type).load();
2251         setTypeAnnotationPositions(tree.pos);
2252         code.emitop2(instanceof_, makeRef(tree.pos(), tree.pattern.type));
2253         result = items.makeStackItem(syms.booleanType);
2254     }
2255 
2256     public void visitIndexed(JCArrayAccess tree) {
2257         genExpr(tree.indexed, tree.indexed.type).load();
2258         genExpr(tree.index, syms.intType).load();
2259         result = items.makeIndexedItem(tree.type);
2260     }
2261 

2283                 sym = binaryQualifier(sym, env.enclClass.type);
2284             result = items.makeStaticItem(sym);
2285         } else {
2286             items.makeThisItem().load();
2287             sym = binaryQualifier(sym, env.enclClass.type);
2288             result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2289         }
2290     }
2291 
2292     //where
2293     private boolean nonVirtualForPrivateAccess(Symbol sym) {
2294         boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2295                              !disableVirtualizedPrivateInvoke;
2296         return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2297     }
2298 
2299     public void visitSelect(JCFieldAccess tree) {
2300         Symbol sym = tree.sym;
2301 
2302         if (tree.name == names._class) {
2303             code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2304             result = items.makeStackItem(pt);
2305             return;
2306        }
2307 
2308         Symbol ssym = TreeInfo.symbol(tree.selected);
2309 
2310         // Are we selecting via super?
2311         boolean selectSuper =
2312             ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2313 
2314         // Are we accessing a member of the superclass in an access method
2315         // resulting from a qualified super?
2316         boolean accessSuper = isAccessSuper(env.enclMethod);
2317 
2318         Item base = (selectSuper)
2319             ? items.makeSuperItem()
2320             : genExpr(tree.selected, tree.selected.type);
2321 
2322         if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2323             // We are seeing a variable that is constant but its selecting
2324             // expression is not.
2325             if ((sym.flags() & STATIC) != 0) {
2326                 if (!selectSuper && (ssym == null || ssym.kind != TYP))

2342             if ((sym.flags() & STATIC) != 0) {
2343                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
2344                     base = base.load();
2345                 base.drop();
2346                 result = items.makeStaticItem(sym);
2347             } else {
2348                 base.load();
2349                 if (sym == syms.lengthVar) {
2350                     code.emitop0(arraylength);
2351                     result = items.makeStackItem(syms.intType);
2352                 } else {
2353                     result = items.
2354                         makeMemberItem(sym,
2355                                        nonVirtualForPrivateAccess(sym) ||
2356                                        selectSuper || accessSuper);
2357                 }
2358             }
2359         }
2360     }
2361 












2362     public boolean isInvokeDynamic(Symbol sym) {
2363         return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
2364     }
2365 
2366     public void visitLiteral(JCLiteral tree) {
2367         if (tree.type.hasTag(BOT)) {
2368             code.emitop0(aconst_null);
2369             result = items.makeStackItem(tree.type);
2370         }
2371         else
2372             result = items.makeImmediateItem(tree.type, tree.value);
2373     }
2374 
2375     public void visitLetExpr(LetExpr tree) {
2376         code.resolvePending();
2377 
2378         int limit = code.nextreg;
2379         int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
2380         try {
2381             genStats(tree.defs, env);

2398 /* ************************************************************************
2399  * main method
2400  *************************************************************************/
2401 
2402     /** Generate code for a class definition.
2403      *  @param env   The attribution environment that belongs to the
2404      *               outermost class containing this class definition.
2405      *               We need this for resolving some additional symbols.
2406      *  @param cdef  The tree representing the class definition.
2407      *  @return      True if code is generated with no errors.
2408      */
2409     public boolean genClass(Env<AttrContext> env, JCClassDecl cdef) {
2410         try {
2411             attrEnv = env;
2412             ClassSymbol c = cdef.sym;
2413             this.toplevel = env.toplevel;
2414             this.endPosTable = toplevel.endPositions;
2415             /* method normalizeDefs() can add references to external classes into the constant pool
2416              */
2417             cdef.defs = normalizeDefs(cdef.defs, c);

2418             generateReferencesToPrunedTree(c);
2419             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
2420             localEnv.toplevel = env.toplevel;
2421             localEnv.enclClass = cdef;
2422 
2423             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2424                 genDef(l.head, localEnv);
2425             }
2426             if (poolWriter.size() > PoolWriter.MAX_ENTRIES) {
2427                 log.error(cdef.pos(), Errors.LimitPool);
2428                 nerrs++;
2429             }
2430             if (nerrs != 0) {
2431                 // if errors, discard code
2432                 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2433                     if (l.head.hasTag(METHODDEF))
2434                         ((JCMethodDecl) l.head).sym.code = null;
2435                 }
2436             }
2437             cdef.defs = List.nil(); // discard trees

  46 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  47 import com.sun.tools.javac.tree.EndPosTable;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 
  50 import static com.sun.tools.javac.code.Flags.*;
  51 import static com.sun.tools.javac.code.Kinds.Kind.*;
  52 import static com.sun.tools.javac.code.TypeTag.*;
  53 import static com.sun.tools.javac.jvm.ByteCodes.*;
  54 import static com.sun.tools.javac.jvm.CRTFlags.*;
  55 import static com.sun.tools.javac.main.Option.*;
  56 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  57 
  58 /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
  59  *
  60  *  <p><b>This is NOT part of any supported API.
  61  *  If you write code that depends on this, you do so at your own risk.
  62  *  This code and its internal interfaces are subject to change or
  63  *  deletion without notice.</b>
  64  */
  65 public class Gen extends JCTree.Visitor {
  66     private static final Object[] NO_STATIC_ARGS = new Object[0];
  67     protected static final Context.Key<Gen> genKey = new Context.Key<>();
  68 
  69     private final Log log;
  70     private final Symtab syms;
  71     private final Check chk;
  72     private final Resolve rs;
  73     private final TreeMaker make;
  74     private final Names names;
  75     private final Target target;
  76     private final Name accessDollar;
  77     private final Types types;
  78     private final Lower lower;
  79     private final Annotate annotate;
  80     private final StringConcat concat;
  81     private final TransValues transValues;
  82 
  83     /** Format of stackmap tables to be generated. */
  84     private final Code.StackMapFormat stackMap;
  85 
  86     /** A type that serves as the expected type for all method expressions.
  87      */
  88     private final Type methodType;
  89 
  90     public static Gen instance(Context context) {
  91         Gen instance = context.get(genKey);
  92         if (instance == null)
  93             instance = new Gen(context);
  94         return instance;
  95     }
  96 
  97     /** Constant pool writer, set by genClass.
  98      */
  99     final PoolWriter poolWriter;
 100 
 101     protected Gen(Context context) {
 102         context.put(genKey, this);
 103 
 104         names = Names.instance(context);
 105         log = Log.instance(context);
 106         syms = Symtab.instance(context);
 107         chk = Check.instance(context);
 108         rs = Resolve.instance(context);
 109         make = TreeMaker.instance(context);
 110         target = Target.instance(context);
 111         types = Types.instance(context);
 112         concat = StringConcat.instance(context);
 113 
 114         methodType = new MethodType(null, null, null, syms.methodClass);
 115         accessDollar = names.
 116             fromString("access" + target.syntheticNameChar());
 117         lower = Lower.instance(context);
 118         transValues = TransValues.instance(context);
 119 
 120         Options options = Options.instance(context);
 121         lineDebugInfo =
 122             options.isUnset(G_CUSTOM) ||
 123             options.isSet(G_CUSTOM, "lines");
 124         varDebugInfo =
 125             options.isUnset(G_CUSTOM)
 126             ? options.isSet(G)
 127             : options.isSet(G_CUSTOM, "vars");
 128         genCrt = options.isSet(XJCOV);
 129         debugCode = options.isSet("debug.code");
 130         disableVirtualizedPrivateInvoke = options.isSet("disableVirtualizedPrivateInvoke");
 131         poolWriter = new PoolWriter(types, names);
 132 
 133         // ignore cldc because we cannot have both stackmap formats
 134         this.stackMap = StackMapFormat.JSR202;
 135         annotate = Annotate.instance(context);
 136         qualifiedSymbolCache = new HashMap<>();
 137         Source source = Source.instance(context);
 138         allowPrimitiveClasses = Source.Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
 139     }
 140 
 141     /** Switches
 142      */
 143     private final boolean lineDebugInfo;
 144     private final boolean varDebugInfo;
 145     private final boolean genCrt;
 146     private final boolean debugCode;
 147     private boolean disableVirtualizedPrivateInvoke;
 148 
 149     /** Code buffer, set by genMethod.
 150      */
 151     private Code code;
 152 
 153     /** Items structure, set by genMethod.
 154      */
 155     private Items items;
 156 
 157     /** Environment for symbol lookup, set by genClass
 158      */

 166      */
 167     private int nerrs = 0;
 168 
 169     /** An object containing mappings of syntax trees to their
 170      *  ending source positions.
 171      */
 172     EndPosTable endPosTable;
 173 
 174     boolean inCondSwitchExpression;
 175     Chain switchExpressionTrueChain;
 176     Chain switchExpressionFalseChain;
 177     List<LocalItem> stackBeforeSwitchExpression;
 178     LocalItem switchResult;
 179 
 180     /** Cache the symbol to reflect the qualifying type.
 181      *  key: corresponding type
 182      *  value: qualified symbol
 183      */
 184     Map<Type, Symbol> qualifiedSymbolCache;
 185 
 186     boolean allowPrimitiveClasses;
 187 
 188     /** Generate code to load an integer constant.
 189      *  @param n     The integer to be loaded.
 190      */
 191     void loadIntConst(int n) {
 192         items.makeImmediateItem(syms.intType, n).load();
 193     }
 194 
 195     /** The opcode that loads a zero constant of a given type code.
 196      *  @param tc   The given type code (@see ByteCode).
 197      */
 198     public static int zero(int tc) {
 199         switch(tc) {
 200         case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
 201             return iconst_0;
 202         case LONGcode:
 203             return lconst_0;
 204         case FLOATcode:
 205             return fconst_0;
 206         case DOUBLEcode:
 207             return dconst_0;

 251             if ((qualifier = qualifiedSymbolCache.get(site)) == null) {
 252                 qualifier = new ClassSymbol(Flags.PUBLIC, site.tsym.name, site, syms.noSymbol);
 253                 qualifiedSymbolCache.put(site, qualifier);
 254             }
 255             return sym.clone(qualifier);
 256         }
 257 
 258         if (sym.owner == site.tsym ||
 259             (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
 260             return sym;
 261         }
 262 
 263         // leave alone methods inherited from Object
 264         // JLS 13.1.
 265         if (sym.owner == syms.objectType.tsym)
 266             return sym;
 267 
 268         return sym.clone(site.tsym);
 269     }
 270 
 271     /** Insert a reference to given type in the constant pool,
 272      *  checking for an array with too many dimensions;
 273      *  return the reference's index.
 274      *  @param type   The type for which a reference is inserted.
 275      */
 276     int makeRef(DiagnosticPosition pos, Type type, boolean emitQtype) {
 277         checkDimension(pos, type);
 278         if (emitQtype) {
 279             return poolWriter.putClass(new ConstantPoolQType(type, types));
 280         } else {
 281             return poolWriter.putClass(type);
 282         }
 283     }
 284 
 285     /** Insert a reference to given type in the constant pool,
 286      *  checking for an array with too many dimensions;
 287      *  return the reference's index.
 288      *  @param type   The type for which a reference is inserted.
 289      */
 290     int makeRef(DiagnosticPosition pos, Type type) {
 291         return makeRef(pos, type, false);
 292     }
 293 
 294     /** Check if the given type is an array with too many dimensions.
 295      */
 296     private Type checkDimension(DiagnosticPosition pos, Type t) {
 297         checkDimensionInternal(pos, t);
 298         return t;
 299     }
 300 
 301     private void checkDimensionInternal(DiagnosticPosition pos, Type t) {
 302         switch (t.getTag()) {
 303         case METHOD:
 304             checkDimension(pos, t.getReturnType());
 305             for (List<Type> args = t.getParameterTypes(); args.nonEmpty(); args = args.tail)
 306                 checkDimension(pos, args.head);
 307             break;
 308         case ARRAY:
 309             if (types.dimensions(t) > ClassFile.MAX_DIMENSIONS) {
 310                 log.error(pos, Errors.LimitDimensions);
 311                 nerrs++;

 325                                     type,
 326                                     env.enclMethod.sym);
 327         code.newLocal(v);
 328         return items.makeLocalItem(v);
 329     }
 330 
 331     /** Generate code to call a non-private method or constructor.
 332      *  @param pos         Position to be used for error reporting.
 333      *  @param site        The type of which the method is a member.
 334      *  @param name        The method's name.
 335      *  @param argtypes    The method's argument types.
 336      *  @param isStatic    A flag that indicates whether we call a
 337      *                     static or instance method.
 338      */
 339     void callMethod(DiagnosticPosition pos,
 340                     Type site, Name name, List<Type> argtypes,
 341                     boolean isStatic) {
 342         Symbol msym = rs.
 343             resolveInternalMethod(pos, attrEnv, site, name, argtypes, null);
 344         if (isStatic) items.makeStaticItem(msym).invoke();
 345         else items.makeMemberItem(msym, names.isInitOrVNew(name)).invoke();
 346     }
 347 
 348     /** Is the given method definition an access method
 349      *  resulting from a qualified super? This is signified by an odd
 350      *  access code.
 351      */
 352     private boolean isAccessSuper(JCMethodDecl enclMethod) {
 353         return
 354             (enclMethod.mods.flags & SYNTHETIC) != 0 &&
 355             isOddAccessName(enclMethod.name);
 356     }
 357 
 358     /** Does given name start with "access$" and end in an odd digit?
 359      */
 360     private boolean isOddAccessName(Name name) {
 361         return
 362             name.startsWith(accessDollar) &&
 363             (name.getByteAt(name.getByteLength() - 1) & 1) == 1;
 364     }
 365 

 548     /** Check a constant value and report if it is a string that is
 549      *  too large.
 550      */
 551     private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
 552         if (nerrs != 0 || // only complain about a long string once
 553             constValue == null ||
 554             !(constValue instanceof String str) ||
 555             str.length() < PoolWriter.MAX_STRING_LENGTH)
 556             return;
 557         log.error(pos, Errors.LimitString);
 558         nerrs++;
 559     }
 560 
 561     /** Insert instance initializer code into initial constructor.
 562      *  @param md        The tree potentially representing a
 563      *                   constructor's definition.
 564      *  @param initCode  The list of instance initializer statements.
 565      *  @param initTAs  Type annotations from the initializer expression.
 566      */
 567     void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
 568         if (names.isInitOrVNew(md.name) && TreeInfo.isInitialConstructor(md)) {
 569             // We are seeing a constructor that does not call another
 570             // constructor of the same class.
 571             List<JCStatement> stats = md.body.stats;
 572             ListBuffer<JCStatement> newstats = new ListBuffer<>();
 573 
 574             if (stats.nonEmpty()) {
 575                 // Copy initializers of synthetic variables generated in
 576                 // the translation of inner classes.
 577                 while (TreeInfo.isSyntheticInit(stats.head)) {
 578                     newstats.append(stats.head);
 579                     stats = stats.tail;
 580                 }
 581                 // Copy superclass constructor call
 582                 newstats.append(stats.head);
 583                 stats = stats.tail;
 584                 // Copy remaining synthetic initializers.
 585                 while (stats.nonEmpty() &&
 586                        TreeInfo.isSyntheticInit(stats.head)) {
 587                     newstats.append(stats.head);
 588                     stats = stats.tail;

 951         // is the method's return type.
 952         this.pt = tree.sym.erasure(types).getReturnType();
 953 
 954         checkDimension(tree.pos(), tree.sym.erasure(types));
 955         genMethod(tree, localEnv, false);
 956     }
 957 //where
 958         /** Generate code for a method.
 959          *  @param tree     The tree representing the method definition.
 960          *  @param env      The environment current for the method body.
 961          *  @param fatcode  A flag that indicates whether all jumps are
 962          *                  within 32K.  We first invoke this method under
 963          *                  the assumption that fatcode == false, i.e. all
 964          *                  jumps are within 32K.  If this fails, fatcode
 965          *                  is set to true and we try again.
 966          */
 967         void genMethod(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
 968             MethodSymbol meth = tree.sym;
 969             int extras = 0;
 970             // Count up extra parameters
 971             if (meth.isInitOrVNew()) {
 972                 extras++;
 973                 if (meth.enclClass().isInner() &&
 974                     !meth.enclClass().isStatic()) {
 975                     extras++;
 976                 }
 977             } else if ((tree.mods.flags & STATIC) == 0) {
 978                 extras++;
 979             }
 980             //      System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG
 981             if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) + extras >
 982                 ClassFile.MAX_PARAMETERS) {
 983                 log.error(tree.pos(), Errors.LimitParameters);
 984                 nerrs++;
 985             }
 986 
 987             else if (tree.body != null) {
 988                 // Create a new code structure and initialize it.
 989                 int startpcCrt = initCode(tree, env, fatcode);
 990 
 991                 try {
 992                     genStat(tree.body, env);
 993                 } catch (CodeSizeOverflow e) {
 994                     // Failed due to code limit, try again with jsr/ret
 995                     startpcCrt = initCode(tree, env, fatcode);
 996                     genStat(tree.body, env);
 997                 }
 998 
 999                 if (code.state.stacksize != 0) {
1000                     log.error(tree.body.pos(), Errors.StackSimError(tree.sym));
1001                     throw new AssertionError();
1002                 }
1003 
1004                 // If last statement could complete normally, insert a
1005                 // return at the end.
1006                 if (code.isAlive()) {
1007                     code.statBegin(TreeInfo.endPos(tree.body));
1008                     if (env.enclMethod == null ||
1009                         env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
1010                         code.emitop0(return_);
1011                     } else if (env.enclMethod.sym.isValueObjectFactory()) {
1012                         items.makeLocalItem(env.enclMethod.factoryProduct).load();
1013                         code.emitop0(areturn);
1014                     } else {
1015                         // sometime dead code seems alive (4415991);
1016                         // generate a small loop instead
1017                         int startpc = code.entryPoint();
1018                         CondItem c = items.makeCondItem(goto_);
1019                         code.resolve(c.jumpTrue(), startpc);
1020                     }
1021                 }
1022                 if (genCrt)
1023                     code.crt.put(tree.body,
1024                                  CRT_BLOCK,
1025                                  startpcCrt,
1026                                  code.curCP());
1027 
1028                 code.endScopes(0);
1029 
1030                 // If we exceeded limits, panic
1031                 if (code.checkLimits(tree.pos(), log)) {
1032                     nerrs++;
1033                     return;

1048 
1049                 // Fill in type annotation positions for exception parameters
1050                 code.fillExceptionParameterPositions();
1051             }
1052         }
1053 
1054         private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
1055             MethodSymbol meth = tree.sym;
1056 
1057             // Create a new code structure.
1058             meth.code = code = new Code(meth,
1059                                         fatcode,
1060                                         lineDebugInfo ? toplevel.lineMap : null,
1061                                         varDebugInfo,
1062                                         stackMap,
1063                                         debugCode,
1064                                         genCrt ? new CRTable(tree, env.toplevel.endPositions)
1065                                                : null,
1066                                         syms,
1067                                         types,
1068                                         poolWriter,
1069                                         allowPrimitiveClasses);
1070             items = new Items(poolWriter, code, syms, types);
1071             if (code.debugCode) {
1072                 System.err.println(meth + " for body " + tree);
1073             }
1074 
1075             // If method is not static, create a new local variable address
1076             // for `this'.
1077             if ((tree.mods.flags & STATIC) == 0) {
1078                 Type selfType = meth.owner.type;
1079                 if (meth.isInitOrVNew() && selfType != syms.objectType)
1080                     selfType = UninitializedType.uninitializedThis(selfType);
1081                 code.setDefined(
1082                         code.newLocal(
1083                             new VarSymbol(FINAL, names._this, selfType, meth.owner)));
1084             }
1085 
1086             // Mark all parameters as defined from the beginning of
1087             // the method.
1088             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1089                 checkDimension(l.head.pos(), l.head.sym.type);
1090                 code.setDefined(code.newLocal(l.head.sym));
1091             }
1092 
1093             // Get ready to generate code for method body.
1094             int startpcCrt = genCrt ? code.curCP() : 0;
1095             code.entryPoint();
1096 
1097             // Suppress initial stackmap
1098             code.pendingStackMap = false;
1099 
1100             return startpcCrt;
1101         }
1102 
1103     public void visitVarDef(JCVariableDecl tree) {
1104         VarSymbol v = tree.sym;
1105         if (tree.init != null) {
1106             checkStringConstant(tree.init.pos(), v.getConstValue());
1107             if (v.getConstValue() == null || varDebugInfo) {
1108                 Assert.check(code.isStatementStart());
1109                 code.newLocal(v);
1110                 genExpr(tree.init, v.erasure(types)).load();
1111                 items.makeLocalItem(v).store();
1112                 Assert.check(code.isStatementStart());
1113             }
1114         } else {
1115             code.newLocal(v);
1116         }
1117         checkDimension(tree.pos(), v.type);
1118         Type localType = v.erasure(types);
1119         if (localType.requiresPreload(env.enclClass.sym)) {
1120             poolWriter.enterPreloadClass((ClassSymbol) localType.tsym);
1121         }
1122     }
1123 
1124     public void visitSkip(JCSkip tree) {
1125     }
1126 
1127     public void visitBlock(JCBlock tree) {
1128         int limit = code.nextreg;
1129         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1130         genStats(tree.stats, localEnv);
1131         // End the scope of all block-local variables in variable info.
1132         if (!env.tree.hasTag(METHODDEF)) {
1133             code.statBegin(tree.endpos);
1134             code.endScopes(limit);
1135             code.pendingStatPos = Position.NOPOS;
1136         }
1137     }
1138 
1139     public void visitDoLoop(JCDoWhileLoop tree) {
1140         genLoop(tree, tree.body, tree.cond, List.nil(), false);
1141     }
1142 
1143     public void visitWhileLoop(JCWhileLoop tree) {
1144         genLoop(tree, tree.body, tree.cond, List.nil(), true);
1145     }
1146 
1147     public void visitWithField(JCWithField tree) {
1148         switch(tree.field.getTag()) {
1149             case IDENT:
1150                 Symbol sym = ((JCIdent) tree.field).sym;
1151                 items.makeThisItem().load();
1152                 genExpr(tree.value, tree.field.type).load();
1153                 sym = binaryQualifier(sym, env.enclClass.type);
1154                 code.emitop2(withfield, sym, PoolWriter::putMember);
1155                 result = items.makeStackItem(tree.type);
1156                 break;
1157             case SELECT:
1158                 JCFieldAccess fieldAccess = (JCFieldAccess) tree.field;
1159                 sym = TreeInfo.symbol(fieldAccess);
1160                 // JDK-8207332: To maintain the order of side effects, must compute value ahead of field
1161                 genExpr(tree.value, tree.field.type).load();
1162                 genExpr(fieldAccess.selected, fieldAccess.selected.type).load();
1163                 if (Code.width(tree.field.type) == 2) {
1164                     code.emitop0(dup_x2);
1165                     code.emitop0(pop);
1166                 } else {
1167                     code.emitop0(swap);
1168                 }
1169                 sym = binaryQualifier(sym, fieldAccess.selected.type);
1170                 code.emitop2(withfield, sym, PoolWriter::putMember);
1171                 result = items.makeStackItem(tree.type);
1172                 break;
1173             default:
1174                 Assert.check(false);
1175         }
1176     }
1177 
1178     public void visitForLoop(JCForLoop tree) {
1179         int limit = code.nextreg;
1180         genStats(tree.init, env);
1181         genLoop(tree, tree.body, tree.cond, tree.step, true);
1182         code.endScopes(limit);
1183     }
1184     //where
1185         /** Generate code for a loop.
1186          *  @param loop       The tree representing the loop.
1187          *  @param body       The loop's body.
1188          *  @param cond       The loop's controlling condition.
1189          *  @param step       "Step" statements to be inserted at end of
1190          *                    each iteration.
1191          *  @param testFirst  True if the loop test belongs before the body.
1192          */
1193         private void genLoop(JCStatement loop,
1194                              JCStatement body,
1195                              JCExpression cond,
1196                              List<JCExpressionStatement> step,
1197                              boolean testFirst) {

2052             result = arr;
2053         } else {
2054             for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
2055                 genExpr(l.head, syms.intType).load();
2056             }
2057             result = makeNewArray(tree.pos(), tree.type, tree.dims.length());
2058         }
2059     }
2060 //where
2061         /** Generate code to create an array with given element type and number
2062          *  of dimensions.
2063          */
2064         Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
2065             Type elemtype = types.elemtype(type);
2066             if (types.dimensions(type) > ClassFile.MAX_DIMENSIONS) {
2067                 log.error(pos, Errors.LimitDimensions);
2068                 nerrs++;
2069             }
2070             int elemcode = Code.arraycode(elemtype);
2071             if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
2072                 code.emitAnewarray(makeRef(pos, elemtype, elemtype.isPrimitiveClass()), type);
2073             } else if (elemcode == 1) {
2074                 code.emitMultianewarray(ndims, makeRef(pos, type), type);
2075             } else {
2076                 code.emitNewarray(elemcode, type);
2077             }
2078             return items.makeStackItem(type);
2079         }
2080 
2081     public void visitParens(JCParens tree) {
2082         result = genExpr(tree.expr, tree.expr.type);
2083     }
2084 
2085     public void visitAssign(JCAssign tree) {
2086         Item l = genExpr(tree.lhs, tree.lhs.type);
2087         genExpr(tree.rhs, tree.lhs.type).load();
2088         if (tree.rhs.type.hasTag(BOT)) {
2089             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
2090                for "regarding a reference as having some other type in a manner that can be proved
2091                correct at compile time."
2092             */

2278                     code.emitop0(opcode >> preShift);
2279                     opcode = opcode & 0xFF;
2280                 }
2281             }
2282             if (opcode >= ifeq && opcode <= if_acmpne ||
2283                 opcode == if_acmp_null || opcode == if_acmp_nonnull) {
2284                 return items.makeCondItem(opcode);
2285             } else {
2286                 code.emitop0(opcode);
2287                 return items.makeStackItem(optype.restype);
2288             }
2289         }
2290 
2291     public void visitTypeCast(JCTypeCast tree) {
2292         result = genExpr(tree.expr, tree.clazz.type).load();
2293         setTypeAnnotationPositions(tree.pos);
2294         // Additional code is only needed if we cast to a reference type
2295         // which is not statically a supertype of the expression's type.
2296         // For basic types, the coerce(...) in genExpr(...) will do
2297         // the conversion.
2298         // primitive reference conversion is a nop when we bifurcate the primitive class, as the VM sees a subtyping relationship.
2299         if (!tree.clazz.type.isPrimitive() &&
2300            !types.isSameType(tree.expr.type, tree.clazz.type) &&
2301             (!tree.clazz.type.isReferenceProjection() || !types.isSameType(tree.clazz.type.valueProjection(), tree.expr.type) || true) &&
2302            !types.isSubtype(tree.expr.type, tree.clazz.type)) {
2303             checkDimension(tree.pos(), tree.clazz.type);
2304             if (tree.clazz.type.isPrimitiveClass()) {
2305                 code.emitop2(checkcast, new ConstantPoolQType(tree.clazz.type, types), PoolWriter::putClass);
2306             } else {
2307                 code.emitop2(checkcast, tree.clazz.type, PoolWriter::putClass);
2308             }
2309 
2310         }
2311     }
2312 
2313     public void visitWildcard(JCWildcard tree) {
2314         throw new AssertionError(this.getClass().getName());
2315     }
2316 
2317     public void visitTypeTest(JCInstanceOf tree) {
2318         genExpr(tree.expr, tree.expr.type).load();
2319         setTypeAnnotationPositions(tree.pos);
2320         code.emitop2(instanceof_, makeRef(tree.pos(), tree.pattern.type));
2321         result = items.makeStackItem(syms.booleanType);
2322     }
2323 
2324     public void visitIndexed(JCArrayAccess tree) {
2325         genExpr(tree.indexed, tree.indexed.type).load();
2326         genExpr(tree.index, syms.intType).load();
2327         result = items.makeIndexedItem(tree.type);
2328     }
2329 

2351                 sym = binaryQualifier(sym, env.enclClass.type);
2352             result = items.makeStaticItem(sym);
2353         } else {
2354             items.makeThisItem().load();
2355             sym = binaryQualifier(sym, env.enclClass.type);
2356             result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2357         }
2358     }
2359 
2360     //where
2361     private boolean nonVirtualForPrivateAccess(Symbol sym) {
2362         boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2363                              !disableVirtualizedPrivateInvoke;
2364         return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2365     }
2366 
2367     public void visitSelect(JCFieldAccess tree) {
2368         Symbol sym = tree.sym;
2369 
2370         if (tree.name == names._class) {
2371             code.emitLdc((LoadableConstant) tree.selected.type, makeRef(tree.pos(), tree.selected.type, tree.selected.type.isPrimitiveClass()));
2372             result = items.makeStackItem(pt);
2373             return;
2374         }
2375 
2376         Symbol ssym = TreeInfo.symbol(tree.selected);
2377 
2378         // Are we selecting via super?
2379         boolean selectSuper =
2380             ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2381 
2382         // Are we accessing a member of the superclass in an access method
2383         // resulting from a qualified super?
2384         boolean accessSuper = isAccessSuper(env.enclMethod);
2385 
2386         Item base = (selectSuper)
2387             ? items.makeSuperItem()
2388             : genExpr(tree.selected, tree.selected.type);
2389 
2390         if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2391             // We are seeing a variable that is constant but its selecting
2392             // expression is not.
2393             if ((sym.flags() & STATIC) != 0) {
2394                 if (!selectSuper && (ssym == null || ssym.kind != TYP))

2410             if ((sym.flags() & STATIC) != 0) {
2411                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
2412                     base = base.load();
2413                 base.drop();
2414                 result = items.makeStaticItem(sym);
2415             } else {
2416                 base.load();
2417                 if (sym == syms.lengthVar) {
2418                     code.emitop0(arraylength);
2419                     result = items.makeStackItem(syms.intType);
2420                 } else {
2421                     result = items.
2422                         makeMemberItem(sym,
2423                                        nonVirtualForPrivateAccess(sym) ||
2424                                        selectSuper || accessSuper);
2425                 }
2426             }
2427         }
2428     }
2429 
2430     public void visitDefaultValue(JCDefaultValue tree) {
2431         if (tree.type.isValueClass()) {
2432             code.emitop2(aconst_init, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
2433         } else if (tree.type.isReference()) {
2434             code.emitop0(aconst_null);
2435         } else {
2436             code.emitop0(zero(Code.typecode(tree.type)));
2437         }
2438         result = items.makeStackItem(tree.type);
2439         return;
2440     }
2441 
2442     public boolean isInvokeDynamic(Symbol sym) {
2443         return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
2444     }
2445 
2446     public void visitLiteral(JCLiteral tree) {
2447         if (tree.type.hasTag(BOT)) {
2448             code.emitop0(aconst_null);
2449             result = items.makeStackItem(tree.type);
2450         }
2451         else
2452             result = items.makeImmediateItem(tree.type, tree.value);
2453     }
2454 
2455     public void visitLetExpr(LetExpr tree) {
2456         code.resolvePending();
2457 
2458         int limit = code.nextreg;
2459         int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
2460         try {
2461             genStats(tree.defs, env);

2478 /* ************************************************************************
2479  * main method
2480  *************************************************************************/
2481 
2482     /** Generate code for a class definition.
2483      *  @param env   The attribution environment that belongs to the
2484      *               outermost class containing this class definition.
2485      *               We need this for resolving some additional symbols.
2486      *  @param cdef  The tree representing the class definition.
2487      *  @return      True if code is generated with no errors.
2488      */
2489     public boolean genClass(Env<AttrContext> env, JCClassDecl cdef) {
2490         try {
2491             attrEnv = env;
2492             ClassSymbol c = cdef.sym;
2493             this.toplevel = env.toplevel;
2494             this.endPosTable = toplevel.endPositions;
2495             /* method normalizeDefs() can add references to external classes into the constant pool
2496              */
2497             cdef.defs = normalizeDefs(cdef.defs, c);
2498             cdef = transValues.translateTopLevelClass(cdef, make);
2499             generateReferencesToPrunedTree(c);
2500             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
2501             localEnv.toplevel = env.toplevel;
2502             localEnv.enclClass = cdef;
2503 
2504             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2505                 genDef(l.head, localEnv);
2506             }
2507             if (poolWriter.size() > PoolWriter.MAX_ENTRIES) {
2508                 log.error(cdef.pos(), Errors.LimitPool);
2509                 nerrs++;
2510             }
2511             if (nerrs != 0) {
2512                 // if errors, discard code
2513                 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2514                     if (l.head.hasTag(METHODDEF))
2515                         ((JCMethodDecl) l.head).sym.code = null;
2516                 }
2517             }
2518             cdef.defs = List.nil(); // discard trees
< prev index next >