< 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 

 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++;

 966                 try {
 967                     genStat(tree.body, env);
 968                 } catch (CodeSizeOverflow e) {
 969                     // Failed due to code limit, try again with jsr/ret
 970                     startpcCrt = initCode(tree, env, fatcode);
 971                     genStat(tree.body, env);
 972                 }
 973 
 974                 if (code.state.stacksize != 0) {
 975                     log.error(tree.body.pos(), Errors.StackSimError(tree.sym));
 976                     throw new AssertionError();
 977                 }
 978 
 979                 // If last statement could complete normally, insert a
 980                 // return at the end.
 981                 if (code.isAlive()) {
 982                     code.statBegin(TreeInfo.endPos(tree.body));
 983                     if (env.enclMethod == null ||
 984                         env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
 985                         code.emitop0(return_);



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

1029             // Create a new code structure.
1030             meth.code = code = new Code(meth,
1031                                         fatcode,
1032                                         lineDebugInfo ? toplevel.lineMap : null,
1033                                         varDebugInfo,
1034                                         stackMap,
1035                                         debugCode,
1036                                         genCrt ? new CRTable(tree, env.toplevel.endPositions)
1037                                                : null,
1038                                         syms,
1039                                         types,
1040                                         poolWriter);
1041             items = new Items(poolWriter, code, syms, types);
1042             if (code.debugCode) {
1043                 System.err.println(meth + " for body " + tree);
1044             }
1045 
1046             // If method is not static, create a new local variable address
1047             // for `this'.
1048             if ((tree.mods.flags & STATIC) == 0) {
1049                 Type selfType = meth.owner.type;
1050                 if (meth.isConstructor() && selfType != syms.objectType)
1051                     selfType = UninitializedType.uninitializedThis(selfType);
1052                 code.setDefined(
1053                         code.newLocal(
1054                             new VarSymbol(FINAL, names._this, selfType, meth.owner)));
1055             }
1056 
1057             // Mark all parameters as defined from the beginning of
1058             // the method.
1059             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1060                 checkDimension(l.head.pos(), l.head.sym.type);
1061                 code.setDefined(code.newLocal(l.head.sym));
1062             }
1063 
1064             // Get ready to generate code for method body.
1065             int startpcCrt = genCrt ? code.curCP() : 0;
1066             code.entryPoint();
1067 
1068             // Suppress initial stackmap
1069             code.pendingStackMap = false;

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































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

1950                     ta.position.updatePosOffset(code.cp);
1951             }
1952         }
1953     }
1954 
1955     public void visitNewClass(JCNewClass tree) {
1956         // Enclosing instances or anonymous classes should have been eliminated
1957         // by now.
1958         Assert.check(tree.encl == null && tree.def == null);
1959         setTypeAnnotationPositions(tree.pos);
1960 
1961         code.emitop2(new_, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
1962         code.emitop0(dup);
1963 
1964         // Generate code for all arguments, where the expected types are
1965         // the parameters of the constructor's external type (that is,
1966         // any implicit outer instance appears as first parameter).
1967         genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
1968 
1969         items.makeMemberItem(tree.constructor, true).invoke();

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

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

2234         if (!tree.clazz.type.isPrimitive() &&
2235            !types.isSameType(tree.expr.type, tree.clazz.type) &&
2236            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
2237             code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);







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

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

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












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

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

2414             generateReferencesToPrunedTree(c);
2415             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
2416             localEnv.toplevel = env.toplevel;
2417             localEnv.enclClass = cdef;
2418 
2419             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2420                 genDef(l.head, localEnv);
2421             }
2422             if (poolWriter.size() > PoolWriter.MAX_ENTRIES) {
2423                 log.error(cdef.pos(), Errors.LimitPool);
2424                 nerrs++;
2425             }
2426             if (nerrs != 0) {
2427                 // if errors, discard code
2428                 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2429                     if (l.head.hasTag(METHODDEF))
2430                         ((JCMethodDecl) l.head).sym.code = null;
2431                 }
2432             }
2433             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 TransPrimitiveClass transPrimitiveClass;
  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         transPrimitiveClass = TransPrimitiveClass.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     }
 138 

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

 983                 try {
 984                     genStat(tree.body, env);
 985                 } catch (CodeSizeOverflow e) {
 986                     // Failed due to code limit, try again with jsr/ret
 987                     startpcCrt = initCode(tree, env, fatcode);
 988                     genStat(tree.body, env);
 989                 }
 990 
 991                 if (code.state.stacksize != 0) {
 992                     log.error(tree.body.pos(), Errors.StackSimError(tree.sym));
 993                     throw new AssertionError();
 994                 }
 995 
 996                 // If last statement could complete normally, insert a
 997                 // return at the end.
 998                 if (code.isAlive()) {
 999                     code.statBegin(TreeInfo.endPos(tree.body));
1000                     if (env.enclMethod == null ||
1001                         env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
1002                         code.emitop0(return_);
1003                     } else if (env.enclMethod.sym.isPrimitiveObjectFactory()) {
1004                         items.makeLocalItem(env.enclMethod.factoryProduct).load();
1005                         code.emitop0(areturn);
1006                     } else {
1007                         // sometime dead code seems alive (4415991);
1008                         // generate a small loop instead
1009                         int startpc = code.entryPoint();
1010                         CondItem c = items.makeCondItem(goto_);
1011                         code.resolve(c.jumpTrue(), startpc);
1012                     }
1013                 }
1014                 if (genCrt)
1015                     code.crt.put(tree.body,
1016                                  CRT_BLOCK,
1017                                  startpcCrt,
1018                                  code.curCP());
1019 
1020                 code.endScopes(0);
1021 
1022                 // If we exceeded limits, panic
1023                 if (code.checkLimits(tree.pos(), log)) {
1024                     nerrs++;
1025                     return;

1049             // Create a new code structure.
1050             meth.code = code = new Code(meth,
1051                                         fatcode,
1052                                         lineDebugInfo ? toplevel.lineMap : null,
1053                                         varDebugInfo,
1054                                         stackMap,
1055                                         debugCode,
1056                                         genCrt ? new CRTable(tree, env.toplevel.endPositions)
1057                                                : null,
1058                                         syms,
1059                                         types,
1060                                         poolWriter);
1061             items = new Items(poolWriter, code, syms, types);
1062             if (code.debugCode) {
1063                 System.err.println(meth + " for body " + tree);
1064             }
1065 
1066             // If method is not static, create a new local variable address
1067             // for `this'.
1068             if ((tree.mods.flags & STATIC) == 0) {
1069                 Type selfType = meth.owner.isPrimitiveClass() ? meth.owner.type.asValueType() : meth.owner.type;
1070                 if (meth.isConstructor() && selfType != syms.objectType)
1071                     selfType = UninitializedType.uninitializedThis(selfType);
1072                 code.setDefined(
1073                         code.newLocal(
1074                             new VarSymbol(FINAL, names._this, selfType, meth.owner)));
1075             }
1076 
1077             // Mark all parameters as defined from the beginning of
1078             // the method.
1079             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1080                 checkDimension(l.head.pos(), l.head.sym.type);
1081                 code.setDefined(code.newLocal(l.head.sym));
1082             }
1083 
1084             // Get ready to generate code for method body.
1085             int startpcCrt = genCrt ? code.curCP() : 0;
1086             code.entryPoint();
1087 
1088             // Suppress initial stackmap
1089             code.pendingStackMap = false;

1114     public void visitBlock(JCBlock tree) {
1115         int limit = code.nextreg;
1116         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1117         genStats(tree.stats, localEnv);
1118         // End the scope of all block-local variables in variable info.
1119         if (!env.tree.hasTag(METHODDEF)) {
1120             code.statBegin(tree.endpos);
1121             code.endScopes(limit);
1122             code.pendingStatPos = Position.NOPOS;
1123         }
1124     }
1125 
1126     public void visitDoLoop(JCDoWhileLoop tree) {
1127         genLoop(tree, tree.body, tree.cond, List.nil(), false);
1128     }
1129 
1130     public void visitWhileLoop(JCWhileLoop tree) {
1131         genLoop(tree, tree.body, tree.cond, List.nil(), true);
1132     }
1133 
1134     public void visitWithField(JCWithField tree) {
1135         switch(tree.field.getTag()) {
1136             case IDENT:
1137                 Symbol sym = ((JCIdent) tree.field).sym;
1138                 items.makeThisItem().load();
1139                 genExpr(tree.value, tree.field.type).load();
1140                 sym = binaryQualifier(sym, env.enclClass.type);
1141                 code.emitop2(withfield, sym, PoolWriter::putMember);
1142                 result = items.makeStackItem(tree.type);
1143                 break;
1144             case SELECT:
1145                 JCFieldAccess fieldAccess = (JCFieldAccess) tree.field;
1146                 sym = TreeInfo.symbol(fieldAccess);
1147                 // JDK-8207332: To maintain the order of side effects, must compute value ahead of field
1148                 genExpr(tree.value, tree.field.type).load();
1149                 genExpr(fieldAccess.selected, fieldAccess.selected.type).load();
1150                 if (Code.width(tree.field.type) == 2) {
1151                     code.emitop0(dup_x2);
1152                     code.emitop0(pop);
1153                 } else {
1154                     code.emitop0(swap);
1155                 }
1156                 sym = binaryQualifier(sym, fieldAccess.selected.type);
1157                 code.emitop2(withfield, sym, PoolWriter::putMember);
1158                 result = items.makeStackItem(tree.type);
1159                 break;
1160             default:
1161                 Assert.check(false);
1162         }
1163     }
1164 
1165     public void visitForLoop(JCForLoop tree) {
1166         int limit = code.nextreg;
1167         genStats(tree.init, env);
1168         genLoop(tree, tree.body, tree.cond, tree.step, true);
1169         code.endScopes(limit);
1170     }
1171     //where
1172         /** Generate code for a loop.
1173          *  @param loop       The tree representing the loop.
1174          *  @param body       The loop's body.
1175          *  @param cond       The loop's controlling condition.
1176          *  @param step       "Step" statements to be inserted at end of
1177          *                    each iteration.
1178          *  @param testFirst  True if the loop test belongs before the body.
1179          */
1180         private void genLoop(JCStatement loop,
1181                              JCStatement body,
1182                              JCExpression cond,
1183                              List<JCExpressionStatement> step,
1184                              boolean testFirst) {

2001                     ta.position.updatePosOffset(code.cp);
2002             }
2003         }
2004     }
2005 
2006     public void visitNewClass(JCNewClass tree) {
2007         // Enclosing instances or anonymous classes should have been eliminated
2008         // by now.
2009         Assert.check(tree.encl == null && tree.def == null);
2010         setTypeAnnotationPositions(tree.pos);
2011 
2012         code.emitop2(new_, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
2013         code.emitop0(dup);
2014 
2015         // Generate code for all arguments, where the expected types are
2016         // the parameters of the constructor's external type (that is,
2017         // any implicit outer instance appears as first parameter).
2018         genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
2019 
2020         items.makeMemberItem(tree.constructor, true).invoke();
2021 
2022         result = items.makeStackItem(tree.type);
2023     }
2024 
2025     public void visitNewArray(JCNewArray tree) {
2026         setTypeAnnotationPositions(tree.pos);
2027 
2028         if (tree.elems != null) {
2029             Type elemtype = types.elemtype(tree.type);
2030             loadIntConst(tree.elems.length());
2031             Item arr = makeNewArray(tree.pos(), tree.type, 1);
2032             int i = 0;
2033             for (List<JCExpression> l = tree.elems; l.nonEmpty(); l = l.tail) {
2034                 arr.duplicate();
2035                 loadIntConst(i);
2036                 i++;
2037                 genExpr(l.head, elemtype).load();
2038                 items.makeIndexedItem(elemtype).store();
2039             }
2040             result = arr;
2041         } else {
2042             for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
2043                 genExpr(l.head, syms.intType).load();
2044             }
2045             result = makeNewArray(tree.pos(), tree.type, tree.dims.length());
2046         }
2047     }
2048 //where
2049         /** Generate code to create an array with given element type and number
2050          *  of dimensions.
2051          */
2052         Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
2053             Type elemtype = types.elemtype(type);
2054             if (types.dimensions(type) > ClassFile.MAX_DIMENSIONS) {
2055                 log.error(pos, Errors.LimitDimensions);
2056                 nerrs++;
2057             }
2058             int elemcode = Code.arraycode(elemtype);
2059             if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
2060                 code.emitAnewarray(makeRef(pos, elemtype, types.isPrimitiveClass(elemtype)), type);
2061             } else if (elemcode == 1) {
2062                 code.emitMultianewarray(ndims, makeRef(pos, type), type);
2063             } else {
2064                 code.emitNewarray(elemcode, type);
2065             }
2066             return items.makeStackItem(type);
2067         }
2068 
2069     public void visitParens(JCParens tree) {
2070         result = genExpr(tree.expr, tree.expr.type);
2071     }
2072 
2073     public void visitAssign(JCAssign tree) {
2074         Item l = genExpr(tree.lhs, tree.lhs.type);
2075         genExpr(tree.rhs, tree.lhs.type).load();
2076         if (tree.rhs.type.hasTag(BOT)) {
2077             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
2078                for "regarding a reference as having some other type in a manner that can be proved
2079                correct at compile time."
2080             */

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

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

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

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