1 /*
   2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.jvm;
  27 
  28 import java.util.*;
  29 
  30 import com.sun.tools.javac.util.*;
  31 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  32 import com.sun.tools.javac.util.List;
  33 import com.sun.tools.javac.code.*;
  34 import com.sun.tools.javac.code.Attribute.TypeCompound;
  35 import com.sun.tools.javac.code.Symbol.VarSymbol;
  36 import com.sun.tools.javac.comp.*;
  37 import com.sun.tools.javac.tree.*;
  38 
  39 import com.sun.tools.javac.code.Symbol.*;
  40 import com.sun.tools.javac.code.Type.*;
  41 import com.sun.tools.javac.jvm.Code.*;
  42 import com.sun.tools.javac.jvm.Items.*;
  43 import com.sun.tools.javac.tree.EndPosTable;
  44 import com.sun.tools.javac.tree.JCTree.*;
  45 
  46 import static com.sun.tools.javac.code.Flags.*;
  47 import static com.sun.tools.javac.code.Kinds.Kind.*;
  48 import static com.sun.tools.javac.code.TypeTag.*;
  49 import static com.sun.tools.javac.jvm.ByteCodes.*;
  50 import static com.sun.tools.javac.jvm.CRTFlags.*;
  51 import static com.sun.tools.javac.main.Option.*;
  52 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  53 
  54 /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
  55  *
  56  *  <p><b>This is NOT part of any supported API.
  57  *  If you write code that depends on this, you do so at your own risk.
  58  *  This code and its internal interfaces are subject to change or
  59  *  deletion without notice.</b>
  60  */
  61 public class Gen extends JCTree.Visitor {
  62     protected static final Context.Key<Gen> genKey = new Context.Key<>();
  63 
  64     private final Log log;
  65     private final Symtab syms;
  66     private final Check chk;
  67     private final Resolve rs;
  68     private final TreeMaker make;
  69     private final Names names;
  70     private final Target target;
  71     private final Map<Type,Symbol> stringBufferAppend;
  72     private Name accessDollar;
  73     private final Types types;
  74     private final Lower lower;
  75     private final Flow flow;
  76     private final Annotate annotate;
  77 
  78     /** Format of stackmap tables to be generated. */
  79     private final Code.StackMapFormat stackMap;
  80 
  81     /** A type that serves as the expected type for all method expressions.
  82      */
  83     private final Type methodType;
  84 
  85     public static Gen instance(Context context) {
  86         Gen instance = context.get(genKey);
  87         if (instance == null)
  88             instance = new Gen(context);
  89         return instance;
  90     }
  91 
  92     /** Constant pool, reset by genClass.
  93      */
  94     private Pool pool;
  95 
  96     protected Gen(Context context) {
  97         context.put(genKey, this);
  98 
  99         names = Names.instance(context);
 100         log = Log.instance(context);
 101         syms = Symtab.instance(context);
 102         chk = Check.instance(context);
 103         rs = Resolve.instance(context);
 104         make = TreeMaker.instance(context);
 105         target = Target.instance(context);
 106         types = Types.instance(context);
 107         methodType = new MethodType(null, null, null, syms.methodClass);
 108         stringBufferAppend = new HashMap<>();
 109         accessDollar = names.
 110             fromString("access" + target.syntheticNameChar());
 111         flow = Flow.instance(context);
 112         lower = Lower.instance(context);
 113 
 114         Options options = Options.instance(context);
 115         lineDebugInfo =
 116             options.isUnset(G_CUSTOM) ||
 117             options.isSet(G_CUSTOM, "lines");
 118         varDebugInfo =
 119             options.isUnset(G_CUSTOM)
 120             ? options.isSet(G)
 121             : options.isSet(G_CUSTOM, "vars");
 122         genCrt = options.isSet(XJCOV);
 123         debugCode = options.isSet("debugcode");
 124         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
 125         allowBetterNullChecks = target.hasObjects();
 126 
 127         {
 128             String concat = options.get("stringConcat");
 129             if (target.hasStringConcatFactory()) {
 130                 if (concat == null) {
 131                     concat = "indyWithConstants";
 132                 }
 133 
 134                 switch (concat) {
 135                     case "inline":
 136                         allowIndyStringConcat = false;
 137                         indyStringConcatConstants = false;
 138                         break;
 139                     case "indy":
 140                         allowIndyStringConcat = true;
 141                         indyStringConcatConstants = false;
 142                         break;
 143                     case "indyWithConstants":
 144                         allowIndyStringConcat = true;
 145                         indyStringConcatConstants = true;
 146                         break;
 147                     default:
 148                         Assert.error("Unknown stringConcat: " + concat);
 149                         throw new IllegalStateException("Unknown stringConcat: " + concat);
 150                 }
 151             } else {
 152                 if (concat != null && !"inline".equals(concat)) {
 153                     Assert.error("StringConcatFactory-based string concat is requested on a platform that does not support it.");
 154                 }
 155                 allowIndyStringConcat = false;
 156                 indyStringConcatConstants = false;
 157             }
 158         }
 159 
 160         pool = new Pool(types);
 161 
 162         // ignore cldc because we cannot have both stackmap formats
 163         this.stackMap = StackMapFormat.JSR202;
 164 
 165         // by default, avoid jsr's for simple finalizers
 166         int setjsrlimit = 50;
 167         String jsrlimitString = options.get("jsrlimit");
 168         if (jsrlimitString != null) {
 169             try {
 170                 setjsrlimit = Integer.parseInt(jsrlimitString);
 171             } catch (NumberFormatException ex) {
 172                 // ignore ill-formed numbers for jsrlimit
 173             }
 174         }
 175         this.jsrlimit = setjsrlimit;
 176         this.useJsrLocally = false; // reset in visitTry
 177         annotate = Annotate.instance(context);
 178     }
 179 
 180     /** Switches
 181      */
 182     private final boolean lineDebugInfo;
 183     private final boolean varDebugInfo;
 184     private final boolean genCrt;
 185     private final boolean debugCode;
 186     private final boolean allowInvokedynamic;
 187     private final boolean allowBetterNullChecks;
 188     private final boolean allowIndyStringConcat;
 189     private final boolean indyStringConcatConstants;
 190 
 191     /** Default limit of (approximate) size of finalizer to inline.
 192      *  Zero means always use jsr.  100 or greater means never use
 193      *  jsr.
 194      */
 195     private final int jsrlimit;
 196 
 197     /** True if jsr is used.
 198      */
 199     private boolean useJsrLocally;
 200 
 201     /** Code buffer, set by genMethod.
 202      */
 203     private Code code;
 204 
 205     /** Items structure, set by genMethod.
 206      */
 207     private Items items;
 208 
 209     /** Environment for symbol lookup, set by genClass
 210      */
 211     private Env<AttrContext> attrEnv;
 212 
 213     /** The top level tree.
 214      */
 215     private JCCompilationUnit toplevel;
 216 
 217     /** The number of code-gen errors in this class.
 218      */
 219     private int nerrs = 0;
 220 
 221     /** An object containing mappings of syntax trees to their
 222      *  ending source positions.
 223      */
 224     EndPosTable endPosTable;
 225 
 226     /** Generate code to load an integer constant.
 227      *  @param n     The integer to be loaded.
 228      */
 229     void loadIntConst(int n) {
 230         items.makeImmediateItem(syms.intType, n).load();
 231     }
 232 
 233     /** The opcode that loads a zero constant of a given type code.
 234      *  @param tc   The given type code (@see ByteCode).
 235      */
 236     public static int zero(int tc) {
 237         switch(tc) {
 238         case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
 239             return iconst_0;
 240         case LONGcode:
 241             return lconst_0;
 242         case FLOATcode:
 243             return fconst_0;
 244         case DOUBLEcode:
 245             return dconst_0;
 246         default:
 247             throw new AssertionError("zero");
 248         }
 249     }
 250 
 251     /** The opcode that loads a one constant of a given type code.
 252      *  @param tc   The given type code (@see ByteCode).
 253      */
 254     public static int one(int tc) {
 255         return zero(tc) + 1;
 256     }
 257 
 258     /** Generate code to load -1 of the given type code (either int or long).
 259      *  @param tc   The given type code (@see ByteCode).
 260      */
 261     void emitMinusOne(int tc) {
 262         if (tc == LONGcode) {
 263             items.makeImmediateItem(syms.longType, new Long(-1)).load();
 264         } else {
 265             code.emitop0(iconst_m1);
 266         }
 267     }
 268 
 269     /** Construct a symbol to reflect the qualifying type that should
 270      *  appear in the byte code as per JLS 13.1.
 271      *
 272      *  For {@literal target >= 1.2}: Clone a method with the qualifier as owner (except
 273      *  for those cases where we need to work around VM bugs).
 274      *
 275      *  For {@literal target <= 1.1}: If qualified variable or method is defined in a
 276      *  non-accessible class, clone it with the qualifier class as owner.
 277      *
 278      *  @param sym    The accessed symbol
 279      *  @param site   The qualifier's type.
 280      */
 281     Symbol binaryQualifier(Symbol sym, Type site) {
 282 
 283         if (site.hasTag(ARRAY)) {
 284             if (sym == syms.lengthVar ||
 285                 sym.owner != syms.arrayClass)
 286                 return sym;
 287             // array clone can be qualified by the array type in later targets
 288             Symbol qualifier = new ClassSymbol(Flags.PUBLIC, site.tsym.name,
 289                                                site, syms.noSymbol);
 290             return sym.clone(qualifier);
 291         }
 292 
 293         if (sym.owner == site.tsym ||
 294             (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
 295             return sym;
 296         }
 297 
 298         // leave alone methods inherited from Object
 299         // JLS 13.1.
 300         if (sym.owner == syms.objectType.tsym)
 301             return sym;
 302 
 303         return sym.clone(site.tsym);
 304     }
 305 
 306     /** Insert a reference to given type in the constant pool,
 307      *  checking for an array with too many dimensions;
 308      *  return the reference's index.
 309      *  @param type   The type for which a reference is inserted.
 310      */
 311     int makeRef(DiagnosticPosition pos, Type type) {
 312         checkDimension(pos, type);
 313         if (type.isAnnotated()) {
 314             return pool.put((Object)type);
 315         } else {
 316             return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
 317         }
 318     }
 319 
 320     /** Check if the given type is an array with too many dimensions.
 321      */
 322     private void checkDimension(DiagnosticPosition pos, Type t) {
 323         switch (t.getTag()) {
 324         case METHOD:
 325             checkDimension(pos, t.getReturnType());
 326             for (List<Type> args = t.getParameterTypes(); args.nonEmpty(); args = args.tail)
 327                 checkDimension(pos, args.head);
 328             break;
 329         case ARRAY:
 330             if (types.dimensions(t) > ClassFile.MAX_DIMENSIONS) {
 331                 log.error(pos, "limit.dimensions");
 332                 nerrs++;
 333             }
 334             break;
 335         default:
 336             break;
 337         }
 338     }
 339 
 340     /** Create a tempory variable.
 341      *  @param type   The variable's type.
 342      */
 343     LocalItem makeTemp(Type type) {
 344         VarSymbol v = new VarSymbol(Flags.SYNTHETIC,
 345                                     names.empty,
 346                                     type,
 347                                     env.enclMethod.sym);
 348         code.newLocal(v);
 349         return items.makeLocalItem(v);
 350     }
 351 
 352     /** Generate code to call a non-private method or constructor.
 353      *  @param pos         Position to be used for error reporting.
 354      *  @param site        The type of which the method is a member.
 355      *  @param name        The method's name.
 356      *  @param argtypes    The method's argument types.
 357      *  @param isStatic    A flag that indicates whether we call a
 358      *                     static or instance method.
 359      */
 360     void callMethod(DiagnosticPosition pos,
 361                     Type site, Name name, List<Type> argtypes,
 362                     boolean isStatic) {
 363         Symbol msym = rs.
 364             resolveInternalMethod(pos, attrEnv, site, name, argtypes, null);
 365         if (isStatic) items.makeStaticItem(msym).invoke();
 366         else items.makeMemberItem(msym, name == names.init).invoke();
 367     }
 368 
 369     /** Is the given method definition an access method
 370      *  resulting from a qualified super? This is signified by an odd
 371      *  access code.
 372      */
 373     private boolean isAccessSuper(JCMethodDecl enclMethod) {
 374         return
 375             (enclMethod.mods.flags & SYNTHETIC) != 0 &&
 376             isOddAccessName(enclMethod.name);
 377     }
 378 
 379     /** Does given name start with "access$" and end in an odd digit?
 380      */
 381     private boolean isOddAccessName(Name name) {
 382         return
 383             name.startsWith(accessDollar) &&
 384             (name.getByteAt(name.getByteLength() - 1) & 1) == 1;
 385     }
 386 
 387 /* ************************************************************************
 388  * Non-local exits
 389  *************************************************************************/
 390 
 391     /** Generate code to invoke the finalizer associated with given
 392      *  environment.
 393      *  Any calls to finalizers are appended to the environments `cont' chain.
 394      *  Mark beginning of gap in catch all range for finalizer.
 395      */
 396     void genFinalizer(Env<GenContext> env) {
 397         if (code.isAlive() && env.info.finalize != null)
 398             env.info.finalize.gen();
 399     }
 400 
 401     /** Generate code to call all finalizers of structures aborted by
 402      *  a non-local
 403      *  exit.  Return target environment of the non-local exit.
 404      *  @param target      The tree representing the structure that's aborted
 405      *  @param env         The environment current at the non-local exit.
 406      */
 407     Env<GenContext> unwind(JCTree target, Env<GenContext> env) {
 408         Env<GenContext> env1 = env;
 409         while (true) {
 410             genFinalizer(env1);
 411             if (env1.tree == target) break;
 412             env1 = env1.next;
 413         }
 414         return env1;
 415     }
 416 
 417     /** Mark end of gap in catch-all range for finalizer.
 418      *  @param env   the environment which might contain the finalizer
 419      *               (if it does, env.info.gaps != null).
 420      */
 421     void endFinalizerGap(Env<GenContext> env) {
 422         if (env.info.gaps != null && env.info.gaps.length() % 2 == 1)
 423             env.info.gaps.append(code.curCP());
 424     }
 425 
 426     /** Mark end of all gaps in catch-all ranges for finalizers of environments
 427      *  lying between, and including to two environments.
 428      *  @param from    the most deeply nested environment to mark
 429      *  @param to      the least deeply nested environment to mark
 430      */
 431     void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {
 432         Env<GenContext> last = null;
 433         while (last != to) {
 434             endFinalizerGap(from);
 435             last = from;
 436             from = from.next;
 437         }
 438     }
 439 
 440     /** Do any of the structures aborted by a non-local exit have
 441      *  finalizers that require an empty stack?
 442      *  @param target      The tree representing the structure that's aborted
 443      *  @param env         The environment current at the non-local exit.
 444      */
 445     boolean hasFinally(JCTree target, Env<GenContext> env) {
 446         while (env.tree != target) {
 447             if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
 448                 return true;
 449             env = env.next;
 450         }
 451         return false;
 452     }
 453 
 454 /* ************************************************************************
 455  * Normalizing class-members.
 456  *************************************************************************/
 457 
 458     /** Distribute member initializer code into constructors and {@code <clinit>}
 459      *  method.
 460      *  @param defs         The list of class member declarations.
 461      *  @param c            The enclosing class.
 462      */
 463     List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
 464         ListBuffer<JCStatement> initCode = new ListBuffer<>();
 465         ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
 466         ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
 467         ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
 468         ListBuffer<JCTree> methodDefs = new ListBuffer<>();
 469         // Sort definitions into three listbuffers:
 470         //  - initCode for instance initializers
 471         //  - clinitCode for class initializers
 472         //  - methodDefs for method definitions
 473         for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
 474             JCTree def = l.head;
 475             switch (def.getTag()) {
 476             case BLOCK:
 477                 JCBlock block = (JCBlock)def;
 478                 if ((block.flags & STATIC) != 0)
 479                     clinitCode.append(block);
 480                 else if ((block.flags & SYNTHETIC) == 0)
 481                     initCode.append(block);
 482                 break;
 483             case METHODDEF:
 484                 methodDefs.append(def);
 485                 break;
 486             case VARDEF:
 487                 JCVariableDecl vdef = (JCVariableDecl) def;
 488                 VarSymbol sym = vdef.sym;
 489                 checkDimension(vdef.pos(), sym.type);
 490                 if (vdef.init != null) {
 491                     if ((sym.flags() & STATIC) == 0) {
 492                         // Always initialize instance variables.
 493                         JCStatement init = make.at(vdef.pos()).
 494                             Assignment(sym, vdef.init);
 495                         initCode.append(init);
 496                         endPosTable.replaceTree(vdef, init);
 497                         initTAs.addAll(getAndRemoveNonFieldTAs(sym));
 498                     } else if (sym.getConstValue() == null) {
 499                         // Initialize class (static) variables only if
 500                         // they are not compile-time constants.
 501                         JCStatement init = make.at(vdef.pos).
 502                             Assignment(sym, vdef.init);
 503                         clinitCode.append(init);
 504                         endPosTable.replaceTree(vdef, init);
 505                         clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
 506                     } else {
 507                         checkStringConstant(vdef.init.pos(), sym.getConstValue());
 508                         /* if the init contains a reference to an external class, add it to the
 509                          * constant's pool
 510                          */
 511                         vdef.init.accept(classReferenceVisitor);
 512                     }
 513                 }
 514                 break;
 515             default:
 516                 Assert.error();
 517             }
 518         }
 519         // Insert any instance initializers into all constructors.
 520         if (initCode.length() != 0) {
 521             List<JCStatement> inits = initCode.toList();
 522             initTAs.addAll(c.getInitTypeAttributes());
 523             List<Attribute.TypeCompound> initTAlist = initTAs.toList();
 524             for (JCTree t : methodDefs) {
 525                 normalizeMethod((JCMethodDecl)t, inits, initTAlist);
 526             }
 527         }
 528         // If there are class initializers, create a <clinit> method
 529         // that contains them as its body.
 530         if (clinitCode.length() != 0) {
 531             MethodSymbol clinit = new MethodSymbol(
 532                 STATIC | (c.flags() & STRICTFP),
 533                 names.clinit,
 534                 new MethodType(
 535                     List.<Type>nil(), syms.voidType,
 536                     List.<Type>nil(), syms.methodClass),
 537                 c);
 538             c.members().enter(clinit);
 539             List<JCStatement> clinitStats = clinitCode.toList();
 540             JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
 541             block.endpos = TreeInfo.endPos(clinitStats.last());
 542             methodDefs.append(make.MethodDef(clinit, block));
 543 
 544             if (!clinitTAs.isEmpty())
 545                 clinit.appendUniqueTypeAttributes(clinitTAs.toList());
 546             if (!c.getClassInitTypeAttributes().isEmpty())
 547                 clinit.appendUniqueTypeAttributes(c.getClassInitTypeAttributes());
 548         }
 549         // Return all method definitions.
 550         return methodDefs.toList();
 551     }
 552 
 553     private List<Attribute.TypeCompound> getAndRemoveNonFieldTAs(VarSymbol sym) {
 554         List<TypeCompound> tas = sym.getRawTypeAttributes();
 555         ListBuffer<Attribute.TypeCompound> fieldTAs = new ListBuffer<>();
 556         ListBuffer<Attribute.TypeCompound> nonfieldTAs = new ListBuffer<>();
 557         for (TypeCompound ta : tas) {
 558             Assert.check(ta.getPosition().type != TargetType.UNKNOWN);
 559             if (ta.getPosition().type == TargetType.FIELD) {
 560                 fieldTAs.add(ta);
 561             } else {
 562                 nonfieldTAs.add(ta);
 563             }
 564         }
 565         sym.setTypeAttributes(fieldTAs.toList());
 566         return nonfieldTAs.toList();
 567     }
 568 
 569     /** Check a constant value and report if it is a string that is
 570      *  too large.
 571      */
 572     private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
 573         if (nerrs != 0 || // only complain about a long string once
 574             constValue == null ||
 575             !(constValue instanceof String) ||
 576             ((String)constValue).length() < Pool.MAX_STRING_LENGTH)
 577             return;
 578         log.error(pos, "limit.string");
 579         nerrs++;
 580     }
 581 
 582     /** Insert instance initializer code into initial constructor.
 583      *  @param md        The tree potentially representing a
 584      *                   constructor's definition.
 585      *  @param initCode  The list of instance initializer statements.
 586      *  @param initTAs  Type annotations from the initializer expression.
 587      */
 588     void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
 589         if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
 590             // We are seeing a constructor that does not call another
 591             // constructor of the same class.
 592             List<JCStatement> stats = md.body.stats;
 593             ListBuffer<JCStatement> newstats = new ListBuffer<>();
 594 
 595             if (stats.nonEmpty()) {
 596                 // Copy initializers of synthetic variables generated in
 597                 // the translation of inner classes.
 598                 while (TreeInfo.isSyntheticInit(stats.head)) {
 599                     newstats.append(stats.head);
 600                     stats = stats.tail;
 601                 }
 602                 // Copy superclass constructor call
 603                 newstats.append(stats.head);
 604                 stats = stats.tail;
 605                 // Copy remaining synthetic initializers.
 606                 while (stats.nonEmpty() &&
 607                        TreeInfo.isSyntheticInit(stats.head)) {
 608                     newstats.append(stats.head);
 609                     stats = stats.tail;
 610                 }
 611                 // Now insert the initializer code.
 612                 newstats.appendList(initCode);
 613                 // And copy all remaining statements.
 614                 while (stats.nonEmpty()) {
 615                     newstats.append(stats.head);
 616                     stats = stats.tail;
 617                 }
 618             }
 619             md.body.stats = newstats.toList();
 620             if (md.body.endpos == Position.NOPOS)
 621                 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
 622 
 623             md.sym.appendUniqueTypeAttributes(initTAs);
 624         }
 625     }
 626 
 627 /* ************************************************************************
 628  * Traversal methods
 629  *************************************************************************/
 630 
 631     /** Visitor argument: The current environment.
 632      */
 633     Env<GenContext> env;
 634 
 635     /** Visitor argument: The expected type (prototype).
 636      */
 637     Type pt;
 638 
 639     /** Visitor result: The item representing the computed value.
 640      */
 641     Item result;
 642 
 643     /** Visitor method: generate code for a definition, catching and reporting
 644      *  any completion failures.
 645      *  @param tree    The definition to be visited.
 646      *  @param env     The environment current at the definition.
 647      */
 648     public void genDef(JCTree tree, Env<GenContext> env) {
 649         Env<GenContext> prevEnv = this.env;
 650         try {
 651             this.env = env;
 652             tree.accept(this);
 653         } catch (CompletionFailure ex) {
 654             chk.completionError(tree.pos(), ex);
 655         } finally {
 656             this.env = prevEnv;
 657         }
 658     }
 659 
 660     /** Derived visitor method: check whether CharacterRangeTable
 661      *  should be emitted, if so, put a new entry into CRTable
 662      *  and call method to generate bytecode.
 663      *  If not, just call method to generate bytecode.
 664      *  @see    #genStat(JCTree, Env)
 665      *
 666      *  @param  tree     The tree to be visited.
 667      *  @param  env      The environment to use.
 668      *  @param  crtFlags The CharacterRangeTable flags
 669      *                   indicating type of the entry.
 670      */
 671     public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {
 672         if (!genCrt) {
 673             genStat(tree, env);
 674             return;
 675         }
 676         int startpc = code.curCP();
 677         genStat(tree, env);
 678         if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK;
 679         code.crt.put(tree, crtFlags, startpc, code.curCP());
 680     }
 681 
 682     /** Derived visitor method: generate code for a statement.
 683      */
 684     public void genStat(JCTree tree, Env<GenContext> env) {
 685         if (code.isAlive()) {
 686             code.statBegin(tree.pos);
 687             genDef(tree, env);
 688         } else if (env.info.isSwitch && tree.hasTag(VARDEF)) {
 689             // variables whose declarations are in a switch
 690             // can be used even if the decl is unreachable.
 691             code.newLocal(((JCVariableDecl) tree).sym);
 692         }
 693     }
 694 
 695     /** Derived visitor method: check whether CharacterRangeTable
 696      *  should be emitted, if so, put a new entry into CRTable
 697      *  and call method to generate bytecode.
 698      *  If not, just call method to generate bytecode.
 699      *  @see    #genStats(List, Env)
 700      *
 701      *  @param  trees    The list of trees to be visited.
 702      *  @param  env      The environment to use.
 703      *  @param  crtFlags The CharacterRangeTable flags
 704      *                   indicating type of the entry.
 705      */
 706     public void genStats(List<JCStatement> trees, Env<GenContext> env, int crtFlags) {
 707         if (!genCrt) {
 708             genStats(trees, env);
 709             return;
 710         }
 711         if (trees.length() == 1) {        // mark one statement with the flags
 712             genStat(trees.head, env, crtFlags | CRT_STATEMENT);
 713         } else {
 714             int startpc = code.curCP();
 715             genStats(trees, env);
 716             code.crt.put(trees, crtFlags, startpc, code.curCP());
 717         }
 718     }
 719 
 720     /** Derived visitor method: generate code for a list of statements.
 721      */
 722     public void genStats(List<? extends JCTree> trees, Env<GenContext> env) {
 723         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
 724             genStat(l.head, env, CRT_STATEMENT);
 725     }
 726 
 727     /** Derived visitor method: check whether CharacterRangeTable
 728      *  should be emitted, if so, put a new entry into CRTable
 729      *  and call method to generate bytecode.
 730      *  If not, just call method to generate bytecode.
 731      *  @see    #genCond(JCTree,boolean)
 732      *
 733      *  @param  tree     The tree to be visited.
 734      *  @param  crtFlags The CharacterRangeTable flags
 735      *                   indicating type of the entry.
 736      */
 737     public CondItem genCond(JCTree tree, int crtFlags) {
 738         if (!genCrt) return genCond(tree, false);
 739         int startpc = code.curCP();
 740         CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);
 741         code.crt.put(tree, crtFlags, startpc, code.curCP());
 742         return item;
 743     }
 744 
 745     /** Derived visitor method: generate code for a boolean
 746      *  expression in a control-flow context.
 747      *  @param _tree         The expression to be visited.
 748      *  @param markBranches The flag to indicate that the condition is
 749      *                      a flow controller so produced conditions
 750      *                      should contain a proper tree to generate
 751      *                      CharacterRangeTable branches for them.
 752      */
 753     public CondItem genCond(JCTree _tree, boolean markBranches) {
 754         JCTree inner_tree = TreeInfo.skipParens(_tree);
 755         if (inner_tree.hasTag(CONDEXPR)) {
 756             JCConditional tree = (JCConditional)inner_tree;
 757             CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
 758             if (cond.isTrue()) {
 759                 code.resolve(cond.trueJumps);
 760                 CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);
 761                 if (markBranches) result.tree = tree.truepart;
 762                 return result;
 763             }
 764             if (cond.isFalse()) {
 765                 code.resolve(cond.falseJumps);
 766                 CondItem result = genCond(tree.falsepart, CRT_FLOW_TARGET);
 767                 if (markBranches) result.tree = tree.falsepart;
 768                 return result;
 769             }
 770             Chain secondJumps = cond.jumpFalse();
 771             code.resolve(cond.trueJumps);
 772             CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
 773             if (markBranches) first.tree = tree.truepart;
 774             Chain falseJumps = first.jumpFalse();
 775             code.resolve(first.trueJumps);
 776             Chain trueJumps = code.branch(goto_);
 777             code.resolve(secondJumps);
 778             CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);
 779             CondItem result = items.makeCondItem(second.opcode,
 780                                       Code.mergeChains(trueJumps, second.trueJumps),
 781                                       Code.mergeChains(falseJumps, second.falseJumps));
 782             if (markBranches) result.tree = tree.falsepart;
 783             return result;
 784         } else {
 785             CondItem result = genExpr(_tree, syms.booleanType).mkCond();
 786             if (markBranches) result.tree = _tree;
 787             return result;
 788         }
 789     }
 790 
 791     /** Visitor class for expressions which might be constant expressions.
 792      *  This class is a subset of TreeScanner. Intended to visit trees pruned by
 793      *  Lower as long as constant expressions looking for references to any
 794      *  ClassSymbol. Any such reference will be added to the constant pool so
 795      *  automated tools can detect class dependencies better.
 796      */
 797     class ClassReferenceVisitor extends JCTree.Visitor {
 798 
 799         @Override
 800         public void visitTree(JCTree tree) {}
 801 
 802         @Override
 803         public void visitBinary(JCBinary tree) {
 804             tree.lhs.accept(this);
 805             tree.rhs.accept(this);
 806         }
 807 
 808         @Override
 809         public void visitSelect(JCFieldAccess tree) {
 810             if (tree.selected.type.hasTag(CLASS)) {
 811                 makeRef(tree.selected.pos(), tree.selected.type);
 812             }
 813         }
 814 
 815         @Override
 816         public void visitIdent(JCIdent tree) {
 817             if (tree.sym.owner instanceof ClassSymbol) {
 818                 pool.put(tree.sym.owner);
 819             }
 820         }
 821 
 822         @Override
 823         public void visitConditional(JCConditional tree) {
 824             tree.cond.accept(this);
 825             tree.truepart.accept(this);
 826             tree.falsepart.accept(this);
 827         }
 828 
 829         @Override
 830         public void visitUnary(JCUnary tree) {
 831             tree.arg.accept(this);
 832         }
 833 
 834         @Override
 835         public void visitParens(JCParens tree) {
 836             tree.expr.accept(this);
 837         }
 838 
 839         @Override
 840         public void visitTypeCast(JCTypeCast tree) {
 841             tree.expr.accept(this);
 842         }
 843     }
 844 
 845     private ClassReferenceVisitor classReferenceVisitor = new ClassReferenceVisitor();
 846 
 847     /** Visitor method: generate code for an expression, catching and reporting
 848      *  any completion failures.
 849      *  @param tree    The expression to be visited.
 850      *  @param pt      The expression's expected type (proto-type).
 851      */
 852     public Item genExpr(JCTree tree, Type pt) {
 853         Type prevPt = this.pt;
 854         try {
 855             if (tree.type.constValue() != null) {
 856                 // Short circuit any expressions which are constants
 857                 tree.accept(classReferenceVisitor);
 858                 checkStringConstant(tree.pos(), tree.type.constValue());
 859                 result = items.makeImmediateItem(tree.type, tree.type.constValue());
 860             } else {
 861                 this.pt = pt;
 862                 tree.accept(this);
 863             }
 864             return result.coerce(pt);
 865         } catch (CompletionFailure ex) {
 866             chk.completionError(tree.pos(), ex);
 867             code.state.stacksize = 1;
 868             return items.makeStackItem(pt);
 869         } finally {
 870             this.pt = prevPt;
 871         }
 872     }
 873 
 874     /** Derived visitor method: generate code for a list of method arguments.
 875      *  @param trees    The argument expressions to be visited.
 876      *  @param pts      The expression's expected types (i.e. the formal parameter
 877      *                  types of the invoked method).
 878      */
 879     public void genArgs(List<JCExpression> trees, List<Type> pts) {
 880         for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) {
 881             genExpr(l.head, pts.head).load();
 882             pts = pts.tail;
 883         }
 884         // require lists be of same length
 885         Assert.check(pts.isEmpty());
 886     }
 887 
 888 /* ************************************************************************
 889  * Visitor methods for statements and definitions
 890  *************************************************************************/
 891 
 892     /** Thrown when the byte code size exceeds limit.
 893      */
 894     public static class CodeSizeOverflow extends RuntimeException {
 895         private static final long serialVersionUID = 0;
 896         public CodeSizeOverflow() {}
 897     }
 898 
 899     public void visitMethodDef(JCMethodDecl tree) {
 900         // Create a new local environment that points pack at method
 901         // definition.
 902         Env<GenContext> localEnv = env.dup(tree);
 903         localEnv.enclMethod = tree;
 904         // The expected type of every return statement in this method
 905         // is the method's return type.
 906         this.pt = tree.sym.erasure(types).getReturnType();
 907 
 908         checkDimension(tree.pos(), tree.sym.erasure(types));
 909         genMethod(tree, localEnv, false);
 910     }
 911 //where
 912         /** Generate code for a method.
 913          *  @param tree     The tree representing the method definition.
 914          *  @param env      The environment current for the method body.
 915          *  @param fatcode  A flag that indicates whether all jumps are
 916          *                  within 32K.  We first invoke this method under
 917          *                  the assumption that fatcode == false, i.e. all
 918          *                  jumps are within 32K.  If this fails, fatcode
 919          *                  is set to true and we try again.
 920          */
 921         void genMethod(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
 922             MethodSymbol meth = tree.sym;
 923             int extras = 0;
 924             // Count up extra parameters
 925             if (meth.isConstructor()) {
 926                 extras++;
 927                 if (meth.enclClass().isInner() &&
 928                     !meth.enclClass().isStatic()) {
 929                     extras++;
 930                 }
 931             } else if ((tree.mods.flags & STATIC) == 0) {
 932                 extras++;
 933             }
 934             //      System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG
 935             if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) + extras >
 936                 ClassFile.MAX_PARAMETERS) {
 937                 log.error(tree.pos(), "limit.parameters");
 938                 nerrs++;
 939             }
 940 
 941             else if (tree.body != null) {
 942                 // Create a new code structure and initialize it.
 943                 int startpcCrt = initCode(tree, env, fatcode);
 944 
 945                 try {
 946                     genStat(tree.body, env);
 947                 } catch (CodeSizeOverflow e) {
 948                     // Failed due to code limit, try again with jsr/ret
 949                     startpcCrt = initCode(tree, env, fatcode);
 950                     genStat(tree.body, env);
 951                 }
 952 
 953                 if (code.state.stacksize != 0) {
 954                     log.error(tree.body.pos(), "stack.sim.error", tree);
 955                     throw new AssertionError();
 956                 }
 957 
 958                 // If last statement could complete normally, insert a
 959                 // return at the end.
 960                 if (code.isAlive()) {
 961                     code.statBegin(TreeInfo.endPos(tree.body));
 962                     if (env.enclMethod == null ||
 963                         env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
 964                         code.emitop0(return_);
 965                     } else {
 966                         // sometime dead code seems alive (4415991);
 967                         // generate a small loop instead
 968                         int startpc = code.entryPoint();
 969                         CondItem c = items.makeCondItem(goto_);
 970                         code.resolve(c.jumpTrue(), startpc);
 971                     }
 972                 }
 973                 if (genCrt)
 974                     code.crt.put(tree.body,
 975                                  CRT_BLOCK,
 976                                  startpcCrt,
 977                                  code.curCP());
 978 
 979                 code.endScopes(0);
 980 
 981                 // If we exceeded limits, panic
 982                 if (code.checkLimits(tree.pos(), log)) {
 983                     nerrs++;
 984                     return;
 985                 }
 986 
 987                 // If we generated short code but got a long jump, do it again
 988                 // with fatCode = true.
 989                 if (!fatcode && code.fatcode) genMethod(tree, env, true);
 990 
 991                 // Clean up
 992                 if(stackMap == StackMapFormat.JSR202) {
 993                     code.lastFrame = null;
 994                     code.frameBeforeLast = null;
 995                 }
 996 
 997                 // Compress exception table
 998                 code.compressCatchTable();
 999 
1000                 // Fill in type annotation positions for exception parameters
1001                 code.fillExceptionParameterPositions();
1002             }
1003         }
1004 
1005         private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
1006             MethodSymbol meth = tree.sym;
1007 
1008             // Create a new code structure.
1009             meth.code = code = new Code(meth,
1010                                         fatcode,
1011                                         lineDebugInfo ? toplevel.lineMap : null,
1012                                         varDebugInfo,
1013                                         stackMap,
1014                                         debugCode,
1015                                         genCrt ? new CRTable(tree, env.toplevel.endPositions)
1016                                                : null,
1017                                         syms,
1018                                         types,
1019                                         pool);
1020             items = new Items(pool, code, syms, types);
1021             if (code.debugCode) {
1022                 System.err.println(meth + " for body " + tree);
1023             }
1024 
1025             // If method is not static, create a new local variable address
1026             // for `this'.
1027             if ((tree.mods.flags & STATIC) == 0) {
1028                 Type selfType = meth.owner.type;
1029                 if (meth.isConstructor() && selfType != syms.objectType)
1030                     selfType = UninitializedType.uninitializedThis(selfType);
1031                 code.setDefined(
1032                         code.newLocal(
1033                             new VarSymbol(FINAL, names._this, selfType, meth.owner)));
1034             }
1035 
1036             // Mark all parameters as defined from the beginning of
1037             // the method.
1038             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1039                 checkDimension(l.head.pos(), l.head.sym.type);
1040                 code.setDefined(code.newLocal(l.head.sym));
1041             }
1042 
1043             // Get ready to generate code for method body.
1044             int startpcCrt = genCrt ? code.curCP() : 0;
1045             code.entryPoint();
1046 
1047             // Suppress initial stackmap
1048             code.pendingStackMap = false;
1049 
1050             return startpcCrt;
1051         }
1052 
1053     public void visitVarDef(JCVariableDecl tree) {
1054         VarSymbol v = tree.sym;
1055         code.newLocal(v);
1056         if (tree.init != null) {
1057             checkStringConstant(tree.init.pos(), v.getConstValue());
1058             if (v.getConstValue() == null || varDebugInfo) {
1059                 genExpr(tree.init, v.erasure(types)).load();
1060                 items.makeLocalItem(v).store();
1061             }
1062         }
1063         checkDimension(tree.pos(), v.type);
1064     }
1065 
1066     public void visitSkip(JCSkip tree) {
1067     }
1068 
1069     public void visitBlock(JCBlock tree) {
1070         int limit = code.nextreg;
1071         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1072         genStats(tree.stats, localEnv);
1073         // End the scope of all block-local variables in variable info.
1074         if (!env.tree.hasTag(METHODDEF)) {
1075             code.statBegin(tree.endpos);
1076             code.endScopes(limit);
1077             code.pendingStatPos = Position.NOPOS;
1078         }
1079     }
1080 
1081     public void visitDoLoop(JCDoWhileLoop tree) {
1082         genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), false);
1083     }
1084 
1085     public void visitWhileLoop(JCWhileLoop tree) {
1086         genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), true);
1087     }
1088 
1089     public void visitForLoop(JCForLoop tree) {
1090         int limit = code.nextreg;
1091         genStats(tree.init, env);
1092         genLoop(tree, tree.body, tree.cond, tree.step, true);
1093         code.endScopes(limit);
1094     }
1095     //where
1096         /** Generate code for a loop.
1097          *  @param loop       The tree representing the loop.
1098          *  @param body       The loop's body.
1099          *  @param cond       The loop's controling condition.
1100          *  @param step       "Step" statements to be inserted at end of
1101          *                    each iteration.
1102          *  @param testFirst  True if the loop test belongs before the body.
1103          */
1104         private void genLoop(JCStatement loop,
1105                              JCStatement body,
1106                              JCExpression cond,
1107                              List<JCExpressionStatement> step,
1108                              boolean testFirst) {
1109             Env<GenContext> loopEnv = env.dup(loop, new GenContext());
1110             int startpc = code.entryPoint();
1111             if (testFirst) { //while or for loop
1112                 CondItem c;
1113                 if (cond != null) {
1114                     code.statBegin(cond.pos);
1115                     c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1116                 } else {
1117                     c = items.makeCondItem(goto_);
1118                 }
1119                 Chain loopDone = c.jumpFalse();
1120                 code.resolve(c.trueJumps);
1121                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1122                 code.resolve(loopEnv.info.cont);
1123                 genStats(step, loopEnv);
1124                 code.resolve(code.branch(goto_), startpc);
1125                 code.resolve(loopDone);
1126             } else {
1127                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1128                 code.resolve(loopEnv.info.cont);
1129                 genStats(step, loopEnv);
1130                 CondItem c;
1131                 if (cond != null) {
1132                     code.statBegin(cond.pos);
1133                     c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1134                 } else {
1135                     c = items.makeCondItem(goto_);
1136                 }
1137                 code.resolve(c.jumpTrue(), startpc);
1138                 code.resolve(c.falseJumps);
1139             }
1140             Chain exit = loopEnv.info.exit;
1141             if (exit != null) {
1142                 code.resolve(exit);
1143                 exit.state.defined.excludeFrom(code.nextreg);
1144             }
1145         }
1146 
1147     public void visitForeachLoop(JCEnhancedForLoop tree) {
1148         throw new AssertionError(); // should have been removed by Lower.
1149     }
1150 
1151     public void visitLabelled(JCLabeledStatement tree) {
1152         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1153         genStat(tree.body, localEnv, CRT_STATEMENT);
1154         Chain exit = localEnv.info.exit;
1155         if (exit != null) {
1156             code.resolve(exit);
1157             exit.state.defined.excludeFrom(code.nextreg);
1158         }
1159     }
1160 
1161     public void visitSwitch(JCSwitch tree) {
1162         int limit = code.nextreg;
1163         Assert.check(!tree.selector.type.hasTag(CLASS));
1164         int startpcCrt = genCrt ? code.curCP() : 0;
1165         Item sel = genExpr(tree.selector, syms.intType);
1166         List<JCCase> cases = tree.cases;
1167         if (cases.isEmpty()) {
1168             // We are seeing:  switch <sel> {}
1169             sel.load().drop();
1170             if (genCrt)
1171                 code.crt.put(TreeInfo.skipParens(tree.selector),
1172                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1173         } else {
1174             // We are seeing a nonempty switch.
1175             sel.load();
1176             if (genCrt)
1177                 code.crt.put(TreeInfo.skipParens(tree.selector),
1178                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1179             Env<GenContext> switchEnv = env.dup(tree, new GenContext());
1180             switchEnv.info.isSwitch = true;
1181 
1182             // Compute number of labels and minimum and maximum label values.
1183             // For each case, store its label in an array.
1184             int lo = Integer.MAX_VALUE;  // minimum label.
1185             int hi = Integer.MIN_VALUE;  // maximum label.
1186             int nlabels = 0;               // number of labels.
1187 
1188             int[] labels = new int[cases.length()];  // the label array.
1189             int defaultIndex = -1;     // the index of the default clause.
1190 
1191             List<JCCase> l = cases;
1192             for (int i = 0; i < labels.length; i++) {
1193                 if (l.head.pat != null) {
1194                     int val = ((Number)l.head.pat.type.constValue()).intValue();
1195                     labels[i] = val;
1196                     if (val < lo) lo = val;
1197                     if (hi < val) hi = val;
1198                     nlabels++;
1199                 } else {
1200                     Assert.check(defaultIndex == -1);
1201                     defaultIndex = i;
1202                 }
1203                 l = l.tail;
1204             }
1205 
1206             // Determine whether to issue a tableswitch or a lookupswitch
1207             // instruction.
1208             long table_space_cost = 4 + ((long) hi - lo + 1); // words
1209             long table_time_cost = 3; // comparisons
1210             long lookup_space_cost = 3 + 2 * (long) nlabels;
1211             long lookup_time_cost = nlabels;
1212             int opcode =
1213                 nlabels > 0 &&
1214                 table_space_cost + 3 * table_time_cost <=
1215                 lookup_space_cost + 3 * lookup_time_cost
1216                 ?
1217                 tableswitch : lookupswitch;
1218 
1219             int startpc = code.curCP();    // the position of the selector operation
1220             code.emitop0(opcode);
1221             code.align(4);
1222             int tableBase = code.curCP();  // the start of the jump table
1223             int[] offsets = null;          // a table of offsets for a lookupswitch
1224             code.emit4(-1);                // leave space for default offset
1225             if (opcode == tableswitch) {
1226                 code.emit4(lo);            // minimum label
1227                 code.emit4(hi);            // maximum label
1228                 for (long i = lo; i <= hi; i++) {  // leave space for jump table
1229                     code.emit4(-1);
1230                 }
1231             } else {
1232                 code.emit4(nlabels);    // number of labels
1233                 for (int i = 0; i < nlabels; i++) {
1234                     code.emit4(-1); code.emit4(-1); // leave space for lookup table
1235                 }
1236                 offsets = new int[labels.length];
1237             }
1238             Code.State stateSwitch = code.state.dup();
1239             code.markDead();
1240 
1241             // For each case do:
1242             l = cases;
1243             for (int i = 0; i < labels.length; i++) {
1244                 JCCase c = l.head;
1245                 l = l.tail;
1246 
1247                 int pc = code.entryPoint(stateSwitch);
1248                 // Insert offset directly into code or else into the
1249                 // offsets table.
1250                 if (i != defaultIndex) {
1251                     if (opcode == tableswitch) {
1252                         code.put4(
1253                             tableBase + 4 * (labels[i] - lo + 3),
1254                             pc - startpc);
1255                     } else {
1256                         offsets[i] = pc - startpc;
1257                     }
1258                 } else {
1259                     code.put4(tableBase, pc - startpc);
1260                 }
1261 
1262                 // Generate code for the statements in this case.
1263                 genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
1264             }
1265 
1266             // Resolve all breaks.
1267             Chain exit = switchEnv.info.exit;
1268             if  (exit != null) {
1269                 code.resolve(exit);
1270                 exit.state.defined.excludeFrom(code.nextreg);
1271             }
1272 
1273             // If we have not set the default offset, we do so now.
1274             if (code.get4(tableBase) == -1) {
1275                 code.put4(tableBase, code.entryPoint(stateSwitch) - startpc);
1276             }
1277 
1278             if (opcode == tableswitch) {
1279                 // Let any unfilled slots point to the default case.
1280                 int defaultOffset = code.get4(tableBase);
1281                 for (long i = lo; i <= hi; i++) {
1282                     int t = (int)(tableBase + 4 * (i - lo + 3));
1283                     if (code.get4(t) == -1)
1284                         code.put4(t, defaultOffset);
1285                 }
1286             } else {
1287                 // Sort non-default offsets and copy into lookup table.
1288                 if (defaultIndex >= 0)
1289                     for (int i = defaultIndex; i < labels.length - 1; i++) {
1290                         labels[i] = labels[i+1];
1291                         offsets[i] = offsets[i+1];
1292                     }
1293                 if (nlabels > 0)
1294                     qsort2(labels, offsets, 0, nlabels - 1);
1295                 for (int i = 0; i < nlabels; i++) {
1296                     int caseidx = tableBase + 8 * (i + 1);
1297                     code.put4(caseidx, labels[i]);
1298                     code.put4(caseidx + 4, offsets[i]);
1299                 }
1300             }
1301         }
1302         code.endScopes(limit);
1303     }
1304 //where
1305         /** Sort (int) arrays of keys and values
1306          */
1307        static void qsort2(int[] keys, int[] values, int lo, int hi) {
1308             int i = lo;
1309             int j = hi;
1310             int pivot = keys[(i+j)/2];
1311             do {
1312                 while (keys[i] < pivot) i++;
1313                 while (pivot < keys[j]) j--;
1314                 if (i <= j) {
1315                     int temp1 = keys[i];
1316                     keys[i] = keys[j];
1317                     keys[j] = temp1;
1318                     int temp2 = values[i];
1319                     values[i] = values[j];
1320                     values[j] = temp2;
1321                     i++;
1322                     j--;
1323                 }
1324             } while (i <= j);
1325             if (lo < j) qsort2(keys, values, lo, j);
1326             if (i < hi) qsort2(keys, values, i, hi);
1327         }
1328 
1329     public void visitSynchronized(JCSynchronized tree) {
1330         int limit = code.nextreg;
1331         // Generate code to evaluate lock and save in temporary variable.
1332         final LocalItem lockVar = makeTemp(syms.objectType);
1333         genExpr(tree.lock, tree.lock.type).load().duplicate();
1334         lockVar.store();
1335 
1336         // Generate code to enter monitor.
1337         code.emitop0(monitorenter);
1338         code.state.lock(lockVar.reg);
1339 
1340         // Generate code for a try statement with given body, no catch clauses
1341         // in a new environment with the "exit-monitor" operation as finalizer.
1342         final Env<GenContext> syncEnv = env.dup(tree, new GenContext());
1343         syncEnv.info.finalize = new GenFinalizer() {
1344             void gen() {
1345                 genLast();
1346                 Assert.check(syncEnv.info.gaps.length() % 2 == 0);
1347                 syncEnv.info.gaps.append(code.curCP());
1348             }
1349             void genLast() {
1350                 if (code.isAlive()) {
1351                     lockVar.load();
1352                     code.emitop0(monitorexit);
1353                     code.state.unlock(lockVar.reg);
1354                 }
1355             }
1356         };
1357         syncEnv.info.gaps = new ListBuffer<>();
1358         genTry(tree.body, List.<JCCatch>nil(), syncEnv);
1359         code.endScopes(limit);
1360     }
1361 
1362     public void visitTry(final JCTry tree) {
1363         // Generate code for a try statement with given body and catch clauses,
1364         // in a new environment which calls the finally block if there is one.
1365         final Env<GenContext> tryEnv = env.dup(tree, new GenContext());
1366         final Env<GenContext> oldEnv = env;
1367         if (!useJsrLocally) {
1368             useJsrLocally =
1369                 (stackMap == StackMapFormat.NONE) &&
1370                 (jsrlimit <= 0 ||
1371                 jsrlimit < 100 &&
1372                 estimateCodeComplexity(tree.finalizer)>jsrlimit);
1373         }
1374         tryEnv.info.finalize = new GenFinalizer() {
1375             void gen() {
1376                 if (useJsrLocally) {
1377                     if (tree.finalizer != null) {
1378                         Code.State jsrState = code.state.dup();
1379                         jsrState.push(Code.jsrReturnValue);
1380                         tryEnv.info.cont =
1381                             new Chain(code.emitJump(jsr),
1382                                       tryEnv.info.cont,
1383                                       jsrState);
1384                     }
1385                     Assert.check(tryEnv.info.gaps.length() % 2 == 0);
1386                     tryEnv.info.gaps.append(code.curCP());
1387                 } else {
1388                     Assert.check(tryEnv.info.gaps.length() % 2 == 0);
1389                     tryEnv.info.gaps.append(code.curCP());
1390                     genLast();
1391                 }
1392             }
1393             void genLast() {
1394                 if (tree.finalizer != null)
1395                     genStat(tree.finalizer, oldEnv, CRT_BLOCK);
1396             }
1397             boolean hasFinalizer() {
1398                 return tree.finalizer != null;
1399             }
1400         };
1401         tryEnv.info.gaps = new ListBuffer<>();
1402         genTry(tree.body, tree.catchers, tryEnv);
1403     }
1404     //where
1405         /** Generate code for a try or synchronized statement
1406          *  @param body      The body of the try or synchronized statement.
1407          *  @param catchers  The lis of catch clauses.
1408          *  @param env       the environment current for the body.
1409          */
1410         void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {
1411             int limit = code.nextreg;
1412             int startpc = code.curCP();
1413             Code.State stateTry = code.state.dup();
1414             genStat(body, env, CRT_BLOCK);
1415             int endpc = code.curCP();
1416             boolean hasFinalizer =
1417                 env.info.finalize != null &&
1418                 env.info.finalize.hasFinalizer();
1419             List<Integer> gaps = env.info.gaps.toList();
1420             code.statBegin(TreeInfo.endPos(body));
1421             genFinalizer(env);
1422             code.statBegin(TreeInfo.endPos(env.tree));
1423             Chain exitChain = code.branch(goto_);
1424             endFinalizerGap(env);
1425             if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
1426                 // start off with exception on stack
1427                 code.entryPoint(stateTry, l.head.param.sym.type);
1428                 genCatch(l.head, env, startpc, endpc, gaps);
1429                 genFinalizer(env);
1430                 if (hasFinalizer || l.tail.nonEmpty()) {
1431                     code.statBegin(TreeInfo.endPos(env.tree));
1432                     exitChain = Code.mergeChains(exitChain,
1433                                                  code.branch(goto_));
1434                 }
1435                 endFinalizerGap(env);
1436             }
1437             if (hasFinalizer) {
1438                 // Create a new register segement to avoid allocating
1439                 // the same variables in finalizers and other statements.
1440                 code.newRegSegment();
1441 
1442                 // Add a catch-all clause.
1443 
1444                 // start off with exception on stack
1445                 int catchallpc = code.entryPoint(stateTry, syms.throwableType);
1446 
1447                 // Register all exception ranges for catch all clause.
1448                 // The range of the catch all clause is from the beginning
1449                 // of the try or synchronized block until the present
1450                 // code pointer excluding all gaps in the current
1451                 // environment's GenContext.
1452                 int startseg = startpc;
1453                 while (env.info.gaps.nonEmpty()) {
1454                     int endseg = env.info.gaps.next().intValue();
1455                     registerCatch(body.pos(), startseg, endseg,
1456                                   catchallpc, 0);
1457                     startseg = env.info.gaps.next().intValue();
1458                 }
1459                 code.statBegin(TreeInfo.finalizerPos(env.tree));
1460                 code.markStatBegin();
1461 
1462                 Item excVar = makeTemp(syms.throwableType);
1463                 excVar.store();
1464                 genFinalizer(env);
1465                 excVar.load();
1466                 registerCatch(body.pos(), startseg,
1467                               env.info.gaps.next().intValue(),
1468                               catchallpc, 0);
1469                 code.emitop0(athrow);
1470                 code.markDead();
1471 
1472                 // If there are jsr's to this finalizer, ...
1473                 if (env.info.cont != null) {
1474                     // Resolve all jsr's.
1475                     code.resolve(env.info.cont);
1476 
1477                     // Mark statement line number
1478                     code.statBegin(TreeInfo.finalizerPos(env.tree));
1479                     code.markStatBegin();
1480 
1481                     // Save return address.
1482                     LocalItem retVar = makeTemp(syms.throwableType);
1483                     retVar.store();
1484 
1485                     // Generate finalizer code.
1486                     env.info.finalize.genLast();
1487 
1488                     // Return.
1489                     code.emitop1w(ret, retVar.reg);
1490                     code.markDead();
1491                 }
1492             }
1493             // Resolve all breaks.
1494             code.resolve(exitChain);
1495 
1496             code.endScopes(limit);
1497         }
1498 
1499         /** Generate code for a catch clause.
1500          *  @param tree     The catch clause.
1501          *  @param env      The environment current in the enclosing try.
1502          *  @param startpc  Start pc of try-block.
1503          *  @param endpc    End pc of try-block.
1504          */
1505         void genCatch(JCCatch tree,
1506                       Env<GenContext> env,
1507                       int startpc, int endpc,
1508                       List<Integer> gaps) {
1509             if (startpc != endpc) {
1510                 List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypeExprs
1511                         = catchTypesWithAnnotations(tree);
1512                 while (gaps.nonEmpty()) {
1513                     for (Pair<List<Attribute.TypeCompound>, JCExpression> subCatch1 : catchTypeExprs) {
1514                         JCExpression subCatch = subCatch1.snd;
1515                         int catchType = makeRef(tree.pos(), subCatch.type);
1516                         int end = gaps.head.intValue();
1517                         registerCatch(tree.pos(),
1518                                       startpc,  end, code.curCP(),
1519                                       catchType);
1520                         for (Attribute.TypeCompound tc :  subCatch1.fst) {
1521                                 tc.position.setCatchInfo(catchType, startpc);
1522                         }
1523                     }
1524                     gaps = gaps.tail;
1525                     startpc = gaps.head.intValue();
1526                     gaps = gaps.tail;
1527                 }
1528                 if (startpc < endpc) {
1529                     for (Pair<List<Attribute.TypeCompound>, JCExpression> subCatch1 : catchTypeExprs) {
1530                         JCExpression subCatch = subCatch1.snd;
1531                         int catchType = makeRef(tree.pos(), subCatch.type);
1532                         registerCatch(tree.pos(),
1533                                       startpc, endpc, code.curCP(),
1534                                       catchType);
1535                         for (Attribute.TypeCompound tc :  subCatch1.fst) {
1536                             tc.position.setCatchInfo(catchType, startpc);
1537                         }
1538                     }
1539                 }
1540                 VarSymbol exparam = tree.param.sym;
1541                 code.statBegin(tree.pos);
1542                 code.markStatBegin();
1543                 int limit = code.nextreg;
1544                 code.newLocal(exparam);
1545                 items.makeLocalItem(exparam).store();
1546                 code.statBegin(TreeInfo.firstStatPos(tree.body));
1547                 genStat(tree.body, env, CRT_BLOCK);
1548                 code.endScopes(limit);
1549                 code.statBegin(TreeInfo.endPos(tree.body));
1550             }
1551         }
1552         // where
1553         List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypesWithAnnotations(JCCatch tree) {
1554             return TreeInfo.isMultiCatch(tree) ?
1555                     catchTypesWithAnnotationsFromMulticatch((JCTypeUnion)tree.param.vartype, tree.param.sym.getRawTypeAttributes()) :
1556                     List.of(new Pair<>(tree.param.sym.getRawTypeAttributes(), tree.param.vartype));
1557         }
1558         // where
1559         List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypesWithAnnotationsFromMulticatch(JCTypeUnion tree, List<TypeCompound> first) {
1560             List<JCExpression> alts = tree.alternatives;
1561             List<Pair<List<TypeCompound>, JCExpression>> res = List.of(new Pair<>(first, alts.head));
1562             alts = alts.tail;
1563 
1564             while(alts != null && alts.head != null) {
1565                 JCExpression alt = alts.head;
1566                 if (alt instanceof JCAnnotatedType) {
1567                     JCAnnotatedType a = (JCAnnotatedType)alt;
1568                     res = res.prepend(new Pair<>(annotate.fromAnnotations(a.annotations), alt));
1569                 } else {
1570                     res = res.prepend(new Pair<>(List.nil(), alt));
1571                 }
1572                 alts = alts.tail;
1573             }
1574             return res.reverse();
1575         }
1576 
1577         /** Register a catch clause in the "Exceptions" code-attribute.
1578          */
1579         void registerCatch(DiagnosticPosition pos,
1580                            int startpc, int endpc,
1581                            int handler_pc, int catch_type) {
1582             char startpc1 = (char)startpc;
1583             char endpc1 = (char)endpc;
1584             char handler_pc1 = (char)handler_pc;
1585             if (startpc1 == startpc &&
1586                 endpc1 == endpc &&
1587                 handler_pc1 == handler_pc) {
1588                 code.addCatch(startpc1, endpc1, handler_pc1,
1589                               (char)catch_type);
1590             } else {
1591                 log.error(pos, "limit.code.too.large.for.try.stmt");
1592                 nerrs++;
1593             }
1594         }
1595 
1596     /** Very roughly estimate the number of instructions needed for
1597      *  the given tree.
1598      */
1599     int estimateCodeComplexity(JCTree tree) {
1600         if (tree == null) return 0;
1601         class ComplexityScanner extends TreeScanner {
1602             int complexity = 0;
1603             public void scan(JCTree tree) {
1604                 if (complexity > jsrlimit) return;
1605                 super.scan(tree);
1606             }
1607             public void visitClassDef(JCClassDecl tree) {}
1608             public void visitDoLoop(JCDoWhileLoop tree)
1609                 { super.visitDoLoop(tree); complexity++; }
1610             public void visitWhileLoop(JCWhileLoop tree)
1611                 { super.visitWhileLoop(tree); complexity++; }
1612             public void visitForLoop(JCForLoop tree)
1613                 { super.visitForLoop(tree); complexity++; }
1614             public void visitSwitch(JCSwitch tree)
1615                 { super.visitSwitch(tree); complexity+=5; }
1616             public void visitCase(JCCase tree)
1617                 { super.visitCase(tree); complexity++; }
1618             public void visitSynchronized(JCSynchronized tree)
1619                 { super.visitSynchronized(tree); complexity+=6; }
1620             public void visitTry(JCTry tree)
1621                 { super.visitTry(tree);
1622                   if (tree.finalizer != null) complexity+=6; }
1623             public void visitCatch(JCCatch tree)
1624                 { super.visitCatch(tree); complexity+=2; }
1625             public void visitConditional(JCConditional tree)
1626                 { super.visitConditional(tree); complexity+=2; }
1627             public void visitIf(JCIf tree)
1628                 { super.visitIf(tree); complexity+=2; }
1629             // note: for break, continue, and return we don't take unwind() into account.
1630             public void visitBreak(JCBreak tree)
1631                 { super.visitBreak(tree); complexity+=1; }
1632             public void visitContinue(JCContinue tree)
1633                 { super.visitContinue(tree); complexity+=1; }
1634             public void visitReturn(JCReturn tree)
1635                 { super.visitReturn(tree); complexity+=1; }
1636             public void visitThrow(JCThrow tree)
1637                 { super.visitThrow(tree); complexity+=1; }
1638             public void visitAssert(JCAssert tree)
1639                 { super.visitAssert(tree); complexity+=5; }
1640             public void visitApply(JCMethodInvocation tree)
1641                 { super.visitApply(tree); complexity+=2; }
1642             public void visitNewClass(JCNewClass tree)
1643                 { scan(tree.encl); scan(tree.args); complexity+=2; }
1644             public void visitNewArray(JCNewArray tree)
1645                 { super.visitNewArray(tree); complexity+=5; }
1646             public void visitAssign(JCAssign tree)
1647                 { super.visitAssign(tree); complexity+=1; }
1648             public void visitAssignop(JCAssignOp tree)
1649                 { super.visitAssignop(tree); complexity+=2; }
1650             public void visitUnary(JCUnary tree)
1651                 { complexity+=1;
1652                   if (tree.type.constValue() == null) super.visitUnary(tree); }
1653             public void visitBinary(JCBinary tree)
1654                 { complexity+=1;
1655                   if (tree.type.constValue() == null) super.visitBinary(tree); }
1656             public void visitTypeTest(JCInstanceOf tree)
1657                 { super.visitTypeTest(tree); complexity+=1; }
1658             public void visitIndexed(JCArrayAccess tree)
1659                 { super.visitIndexed(tree); complexity+=1; }
1660             public void visitSelect(JCFieldAccess tree)
1661                 { super.visitSelect(tree);
1662                   if (tree.sym.kind == VAR) complexity+=1; }
1663             public void visitIdent(JCIdent tree) {
1664                 if (tree.sym.kind == VAR) {
1665                     complexity+=1;
1666                     if (tree.type.constValue() == null &&
1667                         tree.sym.owner.kind == TYP)
1668                         complexity+=1;
1669                 }
1670             }
1671             public void visitLiteral(JCLiteral tree)
1672                 { complexity+=1; }
1673             public void visitTree(JCTree tree) {}
1674             public void visitWildcard(JCWildcard tree) {
1675                 throw new AssertionError(this.getClass().getName());
1676             }
1677         }
1678         ComplexityScanner scanner = new ComplexityScanner();
1679         tree.accept(scanner);
1680         return scanner.complexity;
1681     }
1682 
1683     public void visitIf(JCIf tree) {
1684         int limit = code.nextreg;
1685         Chain thenExit = null;
1686         CondItem c = genCond(TreeInfo.skipParens(tree.cond),
1687                              CRT_FLOW_CONTROLLER);
1688         Chain elseChain = c.jumpFalse();
1689         if (!c.isFalse()) {
1690             code.resolve(c.trueJumps);
1691             genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1692             thenExit = code.branch(goto_);
1693         }
1694         if (elseChain != null) {
1695             code.resolve(elseChain);
1696             if (tree.elsepart != null) {
1697                 genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
1698             }
1699         }
1700         code.resolve(thenExit);
1701         code.endScopes(limit);
1702     }
1703 
1704     public void visitExec(JCExpressionStatement tree) {
1705         // Optimize x++ to ++x and x-- to --x.
1706         JCExpression e = tree.expr;
1707         switch (e.getTag()) {
1708             case POSTINC:
1709                 ((JCUnary) e).setTag(PREINC);
1710                 break;
1711             case POSTDEC:
1712                 ((JCUnary) e).setTag(PREDEC);
1713                 break;
1714         }
1715         genExpr(tree.expr, tree.expr.type).drop();
1716     }
1717 
1718     public void visitBreak(JCBreak tree) {
1719         Env<GenContext> targetEnv = unwind(tree.target, env);
1720         Assert.check(code.state.stacksize == 0);
1721         targetEnv.info.addExit(code.branch(goto_));
1722         endFinalizerGaps(env, targetEnv);
1723     }
1724 
1725     public void visitContinue(JCContinue tree) {
1726         Env<GenContext> targetEnv = unwind(tree.target, env);
1727         Assert.check(code.state.stacksize == 0);
1728         targetEnv.info.addCont(code.branch(goto_));
1729         endFinalizerGaps(env, targetEnv);
1730     }
1731 
1732     public void visitReturn(JCReturn tree) {
1733         int limit = code.nextreg;
1734         final Env<GenContext> targetEnv;
1735 
1736         /* Save and then restore the location of the return in case a finally
1737          * is expanded (with unwind()) in the middle of our bytecodes.
1738          */
1739         int tmpPos = code.pendingStatPos;
1740         if (tree.expr != null) {
1741             Item r = genExpr(tree.expr, pt).load();
1742             if (hasFinally(env.enclMethod, env)) {
1743                 r = makeTemp(pt);
1744                 r.store();
1745             }
1746             targetEnv = unwind(env.enclMethod, env);
1747             code.pendingStatPos = tmpPos;
1748             r.load();
1749             code.emitop0(ireturn + Code.truncate(Code.typecode(pt)));
1750         } else {
1751             targetEnv = unwind(env.enclMethod, env);
1752             code.pendingStatPos = tmpPos;
1753             code.emitop0(return_);
1754         }
1755         endFinalizerGaps(env, targetEnv);
1756         code.endScopes(limit);
1757     }
1758 
1759     public void visitThrow(JCThrow tree) {
1760         genExpr(tree.expr, tree.expr.type).load();
1761         code.emitop0(athrow);
1762     }
1763 
1764 /* ************************************************************************
1765  * Visitor methods for expressions
1766  *************************************************************************/
1767 
1768     public void visitApply(JCMethodInvocation tree) {
1769         setTypeAnnotationPositions(tree.pos);
1770         // Generate code for method.
1771         Item m = genExpr(tree.meth, methodType);
1772         // Generate code for all arguments, where the expected types are
1773         // the parameters of the method's external type (that is, any implicit
1774         // outer instance of a super(...) call appears as first parameter).
1775         MethodSymbol msym = (MethodSymbol)TreeInfo.symbol(tree.meth);
1776         genArgs(tree.args,
1777                 msym.externalType(types).getParameterTypes());
1778         if (!msym.isDynamic()) {
1779             code.statBegin(tree.pos);
1780         }
1781         result = m.invoke();
1782     }
1783 
1784     public void visitConditional(JCConditional tree) {
1785         Chain thenExit = null;
1786         CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER);
1787         Chain elseChain = c.jumpFalse();
1788         if (!c.isFalse()) {
1789             code.resolve(c.trueJumps);
1790             int startpc = genCrt ? code.curCP() : 0;
1791             code.statBegin(tree.truepart.pos);
1792             genExpr(tree.truepart, pt).load();
1793             code.state.forceStackTop(tree.type);
1794             if (genCrt) code.crt.put(tree.truepart, CRT_FLOW_TARGET,
1795                                      startpc, code.curCP());
1796             thenExit = code.branch(goto_);
1797         }
1798         if (elseChain != null) {
1799             code.resolve(elseChain);
1800             int startpc = genCrt ? code.curCP() : 0;
1801             code.statBegin(tree.falsepart.pos);
1802             genExpr(tree.falsepart, pt).load();
1803             code.state.forceStackTop(tree.type);
1804             if (genCrt) code.crt.put(tree.falsepart, CRT_FLOW_TARGET,
1805                                      startpc, code.curCP());
1806         }
1807         code.resolve(thenExit);
1808         result = items.makeStackItem(pt);
1809     }
1810 
1811     private void setTypeAnnotationPositions(int treePos) {
1812         MethodSymbol meth = code.meth;
1813         boolean initOrClinit = code.meth.getKind() == javax.lang.model.element.ElementKind.CONSTRUCTOR
1814                 || code.meth.getKind() == javax.lang.model.element.ElementKind.STATIC_INIT;
1815 
1816         for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) {
1817             if (ta.hasUnknownPosition())
1818                 ta.tryFixPosition();
1819 
1820             if (ta.position.matchesPos(treePos))
1821                 ta.position.updatePosOffset(code.cp);
1822         }
1823 
1824         if (!initOrClinit)
1825             return;
1826 
1827         for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) {
1828             if (ta.hasUnknownPosition())
1829                 ta.tryFixPosition();
1830 
1831             if (ta.position.matchesPos(treePos))
1832                 ta.position.updatePosOffset(code.cp);
1833         }
1834 
1835         ClassSymbol clazz = meth.enclClass();
1836         for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
1837             if (!s.getKind().isField())
1838                 continue;
1839 
1840             for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) {
1841                 if (ta.hasUnknownPosition())
1842                     ta.tryFixPosition();
1843 
1844                 if (ta.position.matchesPos(treePos))
1845                     ta.position.updatePosOffset(code.cp);
1846             }
1847         }
1848     }
1849 
1850     public void visitNewClass(JCNewClass tree) {
1851         // Enclosing instances or anonymous classes should have been eliminated
1852         // by now.
1853         Assert.check(tree.encl == null && tree.def == null);
1854         setTypeAnnotationPositions(tree.pos);
1855 
1856         code.emitop2(new_, makeRef(tree.pos(), tree.type));
1857         code.emitop0(dup);
1858 
1859         // Generate code for all arguments, where the expected types are
1860         // the parameters of the constructor's external type (that is,
1861         // any implicit outer instance appears as first parameter).
1862         genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
1863 
1864         items.makeMemberItem(tree.constructor, true).invoke();
1865         result = items.makeStackItem(tree.type);
1866     }
1867 
1868     public void visitNewArray(JCNewArray tree) {
1869         setTypeAnnotationPositions(tree.pos);
1870 
1871         if (tree.elems != null) {
1872             Type elemtype = types.elemtype(tree.type);
1873             loadIntConst(tree.elems.length());
1874             Item arr = makeNewArray(tree.pos(), tree.type, 1);
1875             int i = 0;
1876             for (List<JCExpression> l = tree.elems; l.nonEmpty(); l = l.tail) {
1877                 arr.duplicate();
1878                 loadIntConst(i);
1879                 i++;
1880                 genExpr(l.head, elemtype).load();
1881                 items.makeIndexedItem(elemtype).store();
1882             }
1883             result = arr;
1884         } else {
1885             for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
1886                 genExpr(l.head, syms.intType).load();
1887             }
1888             result = makeNewArray(tree.pos(), tree.type, tree.dims.length());
1889         }
1890     }
1891 //where
1892         /** Generate code to create an array with given element type and number
1893          *  of dimensions.
1894          */
1895         Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
1896             Type elemtype = types.elemtype(type);
1897             if (types.dimensions(type) > ClassFile.MAX_DIMENSIONS) {
1898                 log.error(pos, "limit.dimensions");
1899                 nerrs++;
1900             }
1901             int elemcode = Code.arraycode(elemtype);
1902             if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
1903                 code.emitAnewarray(makeRef(pos, elemtype), type);
1904             } else if (elemcode == 1) {
1905                 code.emitMultianewarray(ndims, makeRef(pos, type), type);
1906             } else {
1907                 code.emitNewarray(elemcode, type);
1908             }
1909             return items.makeStackItem(type);
1910         }
1911 
1912     public void visitParens(JCParens tree) {
1913         result = genExpr(tree.expr, tree.expr.type);
1914     }
1915 
1916     public void visitAssign(JCAssign tree) {
1917         Item l = genExpr(tree.lhs, tree.lhs.type);
1918         genExpr(tree.rhs, tree.lhs.type).load();
1919         if (tree.rhs.type.hasTag(BOT)) {
1920             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
1921                for "regarding a reference as having some other type in a manner that can be proved
1922                correct at compile time."
1923             */
1924             code.state.forceStackTop(tree.lhs.type);
1925         }
1926         result = items.makeAssignItem(l);
1927     }
1928 
1929     public void visitAssignop(JCAssignOp tree) {
1930         OperatorSymbol operator = (OperatorSymbol) tree.operator;
1931         Item l;
1932         if (operator.opcode == string_add) {
1933             if (allowIndyStringConcat) {
1934                 l = genExpr(tree.lhs, tree.lhs.type);
1935                 emitIndyStringConcat(tree);
1936             } else {
1937                 // Generate code to make a string buffer
1938                 makeStringBuffer(tree.pos());
1939 
1940                 // Generate code for first string, possibly save one
1941                 // copy under buffer
1942                 l = genExpr(tree.lhs, tree.lhs.type);
1943                 if (l.width() > 0) {
1944                     code.emitop0(dup_x1 + 3 * (l.width() - 1));
1945                 }
1946 
1947                 // Load first string and append to buffer.
1948                 l.load();
1949                 appendString(tree.lhs);
1950 
1951                 // Append all other strings to buffer.
1952                 appendStrings(tree.rhs);
1953 
1954                 // Convert buffer to string.
1955                 bufferToString(tree.pos());
1956             }
1957         } else {
1958             // Generate code for first expression
1959             l = genExpr(tree.lhs, tree.lhs.type);
1960 
1961             // If we have an increment of -32768 to +32767 of a local
1962             // int variable we can use an incr instruction instead of
1963             // proceeding further.
1964             if ((tree.hasTag(PLUS_ASG) || tree.hasTag(MINUS_ASG)) &&
1965                 l instanceof LocalItem &&
1966                 tree.lhs.type.getTag().isSubRangeOf(INT) &&
1967                 tree.rhs.type.getTag().isSubRangeOf(INT) &&
1968                 tree.rhs.type.constValue() != null) {
1969                 int ival = ((Number) tree.rhs.type.constValue()).intValue();
1970                 if (tree.hasTag(MINUS_ASG)) ival = -ival;
1971                 ((LocalItem)l).incr(ival);
1972                 result = l;
1973                 return;
1974             }
1975             // Otherwise, duplicate expression, load one copy
1976             // and complete binary operation.
1977             l.duplicate();
1978             l.coerce(operator.type.getParameterTypes().head).load();
1979             completeBinop(tree.lhs, tree.rhs, operator).coerce(tree.lhs.type);
1980         }
1981         result = items.makeAssignItem(l);
1982     }
1983 
1984     public void visitUnary(JCUnary tree) {
1985         OperatorSymbol operator = (OperatorSymbol)tree.operator;
1986         if (tree.hasTag(NOT)) {
1987             CondItem od = genCond(tree.arg, false);
1988             result = od.negate();
1989         } else {
1990             Item od = genExpr(tree.arg, operator.type.getParameterTypes().head);
1991             switch (tree.getTag()) {
1992             case POS:
1993                 result = od.load();
1994                 break;
1995             case NEG:
1996                 result = od.load();
1997                 code.emitop0(operator.opcode);
1998                 break;
1999             case COMPL:
2000                 result = od.load();
2001                 emitMinusOne(od.typecode);
2002                 code.emitop0(operator.opcode);
2003                 break;
2004             case PREINC: case PREDEC:
2005                 od.duplicate();
2006                 if (od instanceof LocalItem &&
2007                     (operator.opcode == iadd || operator.opcode == isub)) {
2008                     ((LocalItem)od).incr(tree.hasTag(PREINC) ? 1 : -1);
2009                     result = od;
2010                 } else {
2011                     od.load();
2012                     code.emitop0(one(od.typecode));
2013                     code.emitop0(operator.opcode);
2014                     // Perform narrowing primitive conversion if byte,
2015                     // char, or short.  Fix for 4304655.
2016                     if (od.typecode != INTcode &&
2017                         Code.truncate(od.typecode) == INTcode)
2018                       code.emitop0(int2byte + od.typecode - BYTEcode);
2019                     result = items.makeAssignItem(od);
2020                 }
2021                 break;
2022             case POSTINC: case POSTDEC:
2023                 od.duplicate();
2024                 if (od instanceof LocalItem &&
2025                     (operator.opcode == iadd || operator.opcode == isub)) {
2026                     Item res = od.load();
2027                     ((LocalItem)od).incr(tree.hasTag(POSTINC) ? 1 : -1);
2028                     result = res;
2029                 } else {
2030                     Item res = od.load();
2031                     od.stash(od.typecode);
2032                     code.emitop0(one(od.typecode));
2033                     code.emitop0(operator.opcode);
2034                     // Perform narrowing primitive conversion if byte,
2035                     // char, or short.  Fix for 4304655.
2036                     if (od.typecode != INTcode &&
2037                         Code.truncate(od.typecode) == INTcode)
2038                       code.emitop0(int2byte + od.typecode - BYTEcode);
2039                     od.store();
2040                     result = res;
2041                 }
2042                 break;
2043             case NULLCHK:
2044                 result = od.load();
2045                 code.emitop0(dup);
2046                 genNullCheck(tree.pos());
2047                 break;
2048             default:
2049                 Assert.error();
2050             }
2051         }
2052     }
2053 
2054     /** Generate a null check from the object value at stack top. */
2055     private void genNullCheck(DiagnosticPosition pos) {
2056         if (allowBetterNullChecks) {
2057             callMethod(pos, syms.objectsType, names.requireNonNull,
2058                     List.of(syms.objectType), true);
2059         } else {
2060             callMethod(pos, syms.objectType, names.getClass,
2061                     List.<Type>nil(), false);
2062         }
2063         code.emitop0(pop);
2064     }
2065 
2066     public void visitBinary(JCBinary tree) {
2067         OperatorSymbol operator = (OperatorSymbol)tree.operator;
2068         if (operator.opcode == string_add) {
2069             if (allowIndyStringConcat) {
2070                 // Emit indified version of String concat
2071                 emitIndyStringConcat(tree);
2072             } else {
2073                 // Create a string buffer.
2074                 makeStringBuffer(tree.pos());
2075                 // Append all strings to buffer.
2076                 appendStrings(tree);
2077                 // Convert buffer to string.
2078                 bufferToString(tree.pos());
2079             }
2080             result = items.makeStackItem(syms.stringType);
2081         } else if (tree.hasTag(AND)) {
2082             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2083             if (!lcond.isFalse()) {
2084                 Chain falseJumps = lcond.jumpFalse();
2085                 code.resolve(lcond.trueJumps);
2086                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2087                 result = items.
2088                     makeCondItem(rcond.opcode,
2089                                  rcond.trueJumps,
2090                                  Code.mergeChains(falseJumps,
2091                                                   rcond.falseJumps));
2092             } else {
2093                 result = lcond;
2094             }
2095         } else if (tree.hasTag(OR)) {
2096             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2097             if (!lcond.isTrue()) {
2098                 Chain trueJumps = lcond.jumpTrue();
2099                 code.resolve(lcond.falseJumps);
2100                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2101                 result = items.
2102                     makeCondItem(rcond.opcode,
2103                                  Code.mergeChains(trueJumps, rcond.trueJumps),
2104                                  rcond.falseJumps);
2105             } else {
2106                 result = lcond;
2107             }
2108         } else {
2109             Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
2110             od.load();
2111             result = completeBinop(tree.lhs, tree.rhs, operator);
2112         }
2113     }
2114 
2115     /**
2116      * Maximum number of slots for String Concat call.
2117      * JDK's StringConcatFactory does not support more than that.
2118      */
2119     private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200;
2120     private static final String TAG_ARG   = "\u0001";
2121     private static final String TAG_CONST = "\u0002";
2122 
2123     List<JCTree> collectStringsRecursive(JCTree tree, List<JCTree> res) {
2124         tree = TreeInfo.skipParens(tree);
2125         if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
2126             JCBinary op = (JCBinary) tree;
2127             if (op.operator.kind == MTH &&
2128                     ((OperatorSymbol) op.operator).opcode == string_add) {
2129                 return res
2130                         .appendList(collectStringsRecursive(op.lhs, res))
2131                         .appendList(collectStringsRecursive(op.rhs, res));
2132             }
2133         }
2134         return res.append(tree);
2135     }
2136 
2137     /** Handle the inline assignments, collect all subtrees */
2138     private void emitIndyStringConcat(JCAssignOp tree) {
2139         List<JCTree> args =
2140                 List.<JCTree>nil()
2141                         .appendList(collectStringsRecursive(tree.lhs, List.nil()))
2142                         .appendList(collectStringsRecursive(tree.rhs, List.nil()));
2143         emitIndyStringConcat(args, tree.type, tree.pos());
2144     }
2145 
2146     /** Handle the string_add operation, collect all subtrees */
2147     private void emitIndyStringConcat(JCBinary tree) {
2148         List<JCTree> args =
2149                 List.<JCTree>nil()
2150                         .appendList(collectStringsRecursive(tree.lhs, List.nil()))
2151                         .appendList(collectStringsRecursive(tree.rhs, List.nil()));
2152         emitIndyStringConcat(args, tree.type, tree.pos());
2153     }
2154 
2155     /** Emit the indy concat for all these arguments, possibly peeling along the way */
2156     private void emitIndyStringConcat(List<JCTree> args, Type type, DiagnosticPosition pos) {
2157         int slots = 0;
2158         int count = 0;
2159 
2160         // Need to peel, so that neither call has more than acceptable number
2161         // of slots for the arguments.
2162         ListBuffer<JCTree> cArgs = new ListBuffer<>();
2163         for (JCTree t : args) {
2164             int needSlots = (t.type.getTag() == LONG || t.type.getTag() == DOUBLE) ? 2 : 1;
2165             if (slots + needSlots >= MAX_INDY_CONCAT_ARG_SLOTS) {
2166                 emitIndyStringConcatOne(cArgs.toList(), type, pos);
2167                 cArgs.clear();
2168                 slots = 0;
2169                 count++;
2170             }
2171             cArgs.add(t);
2172             slots += needSlots;
2173         }
2174 
2175         // Flush the tail slice
2176         if (!cArgs.isEmpty()) {
2177             emitIndyStringConcatOne(cArgs.toList(), type, pos);
2178             count++;
2179         }
2180 
2181         // More that one peel slice produced: concatenate the results
2182         if (count > 1) {
2183             emitIndyStringConcatMerge(count, type, pos);
2184         }
2185     }
2186 
2187     /**
2188      * This code builds the recipe, static and dynamic arguments for calling JDK's
2189      * StringConcatFactory. See the interface description there.
2190      *
2191      * We also bypass empty strings, because they have no meaning at this level. This
2192      * captures the Java language trick to force String concat with e.g. ("" + int)-like
2193      * expression. Down here, we already know we are in String concat business, and do
2194      * not require these markers.
2195      */
2196     private void emitIndyStringConcatOne(List<JCTree> args, Type type, DiagnosticPosition pos) {
2197         Assert.check(!args.isEmpty(), "Arguments list is empty");
2198 
2199         StringBuilder recipe = new StringBuilder(args.size());
2200         ListBuffer<Type> dynamicArgs = new ListBuffer<>();
2201         ListBuffer<Object> staticArgs = new ListBuffer<>();
2202 
2203         if (indyStringConcatConstants) {
2204             for (JCTree arg : args) {
2205                 Object constVal = arg.type.constValue();
2206                 if ("".equals(constVal)) continue;
2207                 if (arg.type == syms.botType) {
2208                     // Concat the null into the recipe right away
2209                     recipe.append("null");
2210                 } else if (constVal != null) {
2211                     // Concat the String representation of the constant, except
2212                     // for the case it contains special tags, which requires us
2213                     // to expose it as detached constant.
2214                     String a = arg.type.stringValue();
2215                     if (a.contains(TAG_CONST) || a.contains(TAG_ARG)) {
2216                         recipe.append(TAG_CONST);
2217                         staticArgs.add(a);
2218                     } else {
2219                         recipe.append(a);
2220                     }
2221                 } else {
2222                     // Ordinary arguments come through the dynamic arguments.
2223                     recipe.append(TAG_ARG);
2224                     dynamicArgs.add(arg.type);
2225                     genExpr(arg, arg.type).load();
2226                 }
2227             }
2228         } else {
2229             for (JCTree arg : args) {
2230                 Object constVal = arg.type.constValue();
2231                 if ("".equals(constVal)) continue;
2232                 if (arg.type == syms.botType) {
2233                     dynamicArgs.add(syms.voidClassType);
2234                 } else {
2235                     dynamicArgs.add(arg.type);
2236                 }
2237                 genExpr(arg, arg.type).load();
2238             }
2239         }
2240 
2241         indyStringConcatDoCall(type, pos, recipe.toString(), staticArgs, dynamicArgs);
2242     }
2243 
2244     /** Special version for concatenating the known number of known Strings */
2245     private void emitIndyStringConcatMerge(int count, Type type, DiagnosticPosition pos) {
2246         Assert.check(count != 0, "Arguments list is empty");
2247         Assert.check(count <= MAX_INDY_CONCAT_ARG_SLOTS, "Too many arguments for concatenation");
2248 
2249         // All arguments are assumed to be non-constant Strings
2250         StringBuilder recipe = new StringBuilder(count);
2251         ListBuffer<Type> argTypes = new ListBuffer<>();
2252         for (int c = 0; c < count; c++) {
2253             argTypes.append(syms.stringType);
2254             recipe.append(TAG_ARG);
2255         }
2256 
2257         indyStringConcatDoCall(type, pos, recipe.toString(), new ListBuffer<>(), argTypes);
2258     }
2259 
2260     /** Produce the actual invokedynamic call to StringConcatFactory */
2261     private void indyStringConcatDoCall(Type type, DiagnosticPosition pos, String recipe, ListBuffer<Object> staticArgs, ListBuffer<Type> dynamicArgTypes) {
2262         MethodType indyType = new MethodType(dynamicArgTypes.toList(),
2263                 type,
2264                 List.<Type>nil(),
2265                 syms.methodClass);
2266 
2267         int prevPos = make.pos;
2268         try {
2269             make.at(pos);
2270 
2271             DynamicMethodSymbol dynSym;
2272 
2273             if (indyStringConcatConstants) {
2274                 ListBuffer<Type> constTypes = new ListBuffer<>();
2275                 ListBuffer<Object> constants = new ListBuffer<>();
2276                 for (Object t : staticArgs) {
2277                     constants.add(t);
2278                     constTypes.add(syms.stringType);
2279                 }
2280 
2281                 List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
2282                         syms.stringType,
2283                         syms.methodTypeType)
2284                         .append(syms.stringType)
2285                         .appendList(constTypes);
2286 
2287                 Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, syms.stringConcatFactory,
2288                         names.makeConcatWithConstants, bsm_staticArgs, List.<Type>nil());
2289 
2290                 dynSym = new DynamicMethodSymbol(names.makeConcatWithConstants,
2291                         syms.noSymbol,
2292                         ClassFile.REF_invokeStatic,
2293                         (MethodSymbol)bsm,
2294                         indyType,
2295                         List.<Object>of(recipe).appendList(constants).toArray());
2296             } else {
2297                 List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
2298                         syms.stringType,
2299                         syms.methodTypeType);
2300 
2301                 Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, syms.stringConcatFactory,
2302                         names.makeConcat, bsm_staticArgs, List.<Type>nil());
2303 
2304                 dynSym = new DynamicMethodSymbol(names.makeConcat,
2305                         syms.noSymbol,
2306                         ClassFile.REF_invokeStatic,
2307                         (MethodSymbol)bsm,
2308                         indyType,
2309                         List.nil().toArray());
2310             }
2311 
2312             Item item = items.makeDynamicItem(dynSym);
2313             item.invoke();
2314         } finally {
2315             make.at(prevPos);
2316         }
2317     }
2318 
2319 //where
2320         /** Make a new string buffer.
2321          */
2322         void makeStringBuffer(DiagnosticPosition pos) {
2323             code.emitop2(new_, makeRef(pos, syms.stringBuilderType));
2324             code.emitop0(dup);
2325             callMethod(
2326                     pos, syms.stringBuilderType, names.init, List.<Type>nil(), false);
2327         }
2328 
2329         /** Append value (on tos) to string buffer (on tos - 1).
2330          */
2331         void appendString(JCTree tree) {
2332             Type t = tree.type.baseType();
2333             if (!t.isPrimitive() && t.tsym != syms.stringType.tsym) {
2334                 t = syms.objectType;
2335             }
2336             items.makeMemberItem(getStringBufferAppend(tree, t), false).invoke();
2337         }
2338         Symbol getStringBufferAppend(JCTree tree, Type t) {
2339             Assert.checkNull(t.constValue());
2340             Symbol method = stringBufferAppend.get(t);
2341             if (method == null) {
2342                 method = rs.resolveInternalMethod(tree.pos(),
2343                                                   attrEnv,
2344                                                   syms.stringBuilderType,
2345                                                   names.append,
2346                                                   List.of(t),
2347                                                   null);
2348                 stringBufferAppend.put(t, method);
2349             }
2350             return method;
2351         }
2352 
2353         /** Add all strings in tree to string buffer.
2354          */
2355         void appendStrings(JCTree tree) {
2356             tree = TreeInfo.skipParens(tree);
2357             if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
2358                 JCBinary op = (JCBinary) tree;
2359                 if (op.operator.kind == MTH &&
2360                     ((OperatorSymbol) op.operator).opcode == string_add) {
2361                     appendStrings(op.lhs);
2362                     appendStrings(op.rhs);
2363                     return;
2364                 }
2365             }
2366             genExpr(tree, tree.type).load();
2367             appendString(tree);
2368         }
2369 
2370         /** Convert string buffer on tos to string.
2371          */
2372         void bufferToString(DiagnosticPosition pos) {
2373             callMethod(
2374                     pos,
2375                     syms.stringBuilderType,
2376                     names.toString,
2377                     List.<Type>nil(),
2378                     false);
2379         }
2380 
2381         /** Complete generating code for operation, with left operand
2382          *  already on stack.
2383          *  @param lhs       The tree representing the left operand.
2384          *  @param rhs       The tree representing the right operand.
2385          *  @param operator  The operator symbol.
2386          */
2387         Item completeBinop(JCTree lhs, JCTree rhs, OperatorSymbol operator) {
2388             MethodType optype = (MethodType)operator.type;
2389             int opcode = operator.opcode;
2390             if (opcode >= if_icmpeq && opcode <= if_icmple &&
2391                 rhs.type.constValue() instanceof Number &&
2392                 ((Number) rhs.type.constValue()).intValue() == 0) {
2393                 opcode = opcode + (ifeq - if_icmpeq);
2394             } else if (opcode >= if_acmpeq && opcode <= if_acmpne &&
2395                        TreeInfo.isNull(rhs)) {
2396                 opcode = opcode + (if_acmp_null - if_acmpeq);
2397             } else {
2398                 // The expected type of the right operand is
2399                 // the second parameter type of the operator, except for
2400                 // shifts with long shiftcount, where we convert the opcode
2401                 // to a short shift and the expected type to int.
2402                 Type rtype = operator.erasure(types).getParameterTypes().tail.head;
2403                 if (opcode >= ishll && opcode <= lushrl) {
2404                     opcode = opcode + (ishl - ishll);
2405                     rtype = syms.intType;
2406                 }
2407                 // Generate code for right operand and load.
2408                 genExpr(rhs, rtype).load();
2409                 // If there are two consecutive opcode instructions,
2410                 // emit the first now.
2411                 if (opcode >= (1 << preShift)) {
2412                     code.emitop0(opcode >> preShift);
2413                     opcode = opcode & 0xFF;
2414                 }
2415             }
2416             if (opcode >= ifeq && opcode <= if_acmpne ||
2417                 opcode == if_acmp_null || opcode == if_acmp_nonnull) {
2418                 return items.makeCondItem(opcode);
2419             } else {
2420                 code.emitop0(opcode);
2421                 return items.makeStackItem(optype.restype);
2422             }
2423         }
2424 
2425     public void visitTypeCast(JCTypeCast tree) {
2426         setTypeAnnotationPositions(tree.pos);
2427         result = genExpr(tree.expr, tree.clazz.type).load();
2428         // Additional code is only needed if we cast to a reference type
2429         // which is not statically a supertype of the expression's type.
2430         // For basic types, the coerce(...) in genExpr(...) will do
2431         // the conversion.
2432         if (!tree.clazz.type.isPrimitive() &&
2433            !types.isSameType(tree.expr.type, tree.clazz.type) &&
2434            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
2435             code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
2436         }
2437     }
2438 
2439     public void visitWildcard(JCWildcard tree) {
2440         throw new AssertionError(this.getClass().getName());
2441     }
2442 
2443     public void visitTypeTest(JCInstanceOf tree) {
2444         setTypeAnnotationPositions(tree.pos);
2445         genExpr(tree.expr, tree.expr.type).load();
2446         code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type));
2447         result = items.makeStackItem(syms.booleanType);
2448     }
2449 
2450     public void visitIndexed(JCArrayAccess tree) {
2451         genExpr(tree.indexed, tree.indexed.type).load();
2452         genExpr(tree.index, syms.intType).load();
2453         result = items.makeIndexedItem(tree.type);
2454     }
2455 
2456     public void visitIdent(JCIdent tree) {
2457         Symbol sym = tree.sym;
2458         if (tree.name == names._this || tree.name == names._super) {
2459             Item res = tree.name == names._this
2460                 ? items.makeThisItem()
2461                 : items.makeSuperItem();
2462             if (sym.kind == MTH) {
2463                 // Generate code to address the constructor.
2464                 res.load();
2465                 res = items.makeMemberItem(sym, true);
2466             }
2467             result = res;
2468         } else if (sym.kind == VAR && sym.owner.kind == MTH) {
2469             result = items.makeLocalItem((VarSymbol)sym);
2470         } else if (isInvokeDynamic(sym)) {
2471             result = items.makeDynamicItem(sym);
2472         } else if ((sym.flags() & STATIC) != 0) {
2473             if (!isAccessSuper(env.enclMethod))
2474                 sym = binaryQualifier(sym, env.enclClass.type);
2475             result = items.makeStaticItem(sym);
2476         } else {
2477             items.makeThisItem().load();
2478             sym = binaryQualifier(sym, env.enclClass.type);
2479             result = items.makeMemberItem(sym, (sym.flags() & PRIVATE) != 0);
2480         }
2481     }
2482 
2483     public void visitSelect(JCFieldAccess tree) {
2484         Symbol sym = tree.sym;
2485 
2486         if (tree.name == names._class) {
2487             code.emitLdc(makeRef(tree.pos(), tree.selected.type));
2488             result = items.makeStackItem(pt);
2489             return;
2490        }
2491 
2492         Symbol ssym = TreeInfo.symbol(tree.selected);
2493 
2494         // Are we selecting via super?
2495         boolean selectSuper =
2496             ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2497 
2498         // Are we accessing a member of the superclass in an access method
2499         // resulting from a qualified super?
2500         boolean accessSuper = isAccessSuper(env.enclMethod);
2501 
2502         Item base = (selectSuper)
2503             ? items.makeSuperItem()
2504             : genExpr(tree.selected, tree.selected.type);
2505 
2506         if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2507             // We are seeing a variable that is constant but its selecting
2508             // expression is not.
2509             if ((sym.flags() & STATIC) != 0) {
2510                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
2511                     base = base.load();
2512                 base.drop();
2513             } else {
2514                 base.load();
2515                 genNullCheck(tree.selected.pos());
2516             }
2517             result = items.
2518                 makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
2519         } else {
2520             if (isInvokeDynamic(sym)) {
2521                 result = items.makeDynamicItem(sym);
2522                 return;
2523             } else {
2524                 sym = binaryQualifier(sym, tree.selected.type);
2525             }
2526             if ((sym.flags() & STATIC) != 0) {
2527                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
2528                     base = base.load();
2529                 base.drop();
2530                 result = items.makeStaticItem(sym);
2531             } else {
2532                 base.load();
2533                 if (sym == syms.lengthVar) {
2534                     code.emitop0(arraylength);
2535                     result = items.makeStackItem(syms.intType);
2536                 } else {
2537                     result = items.
2538                         makeMemberItem(sym,
2539                                        (sym.flags() & PRIVATE) != 0 ||
2540                                        selectSuper || accessSuper);
2541                 }
2542             }
2543         }
2544     }
2545 
2546     public boolean isInvokeDynamic(Symbol sym) {
2547         return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
2548     }
2549 
2550     public void visitLiteral(JCLiteral tree) {
2551         if (tree.type.hasTag(BOT)) {
2552             code.emitop0(aconst_null);
2553             result = items.makeStackItem(tree.type);
2554         }
2555         else
2556             result = items.makeImmediateItem(tree.type, tree.value);
2557     }
2558 
2559     public void visitLetExpr(LetExpr tree) {
2560         int limit = code.nextreg;
2561         genStats(tree.defs, env);
2562         result = genExpr(tree.expr, tree.expr.type).load();
2563         code.endScopes(limit);
2564     }
2565 
2566     private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
2567         List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
2568         if (prunedInfo != null) {
2569             for (JCTree prunedTree: prunedInfo) {
2570                 prunedTree.accept(classReferenceVisitor);
2571             }
2572         }
2573     }
2574 
2575 /* ************************************************************************
2576  * main method
2577  *************************************************************************/
2578 
2579     /** Generate code for a class definition.
2580      *  @param env   The attribution environment that belongs to the
2581      *               outermost class containing this class definition.
2582      *               We need this for resolving some additional symbols.
2583      *  @param cdef  The tree representing the class definition.
2584      *  @return      True if code is generated with no errors.
2585      */
2586     public boolean genClass(Env<AttrContext> env, JCClassDecl cdef) {
2587         try {
2588             attrEnv = env;
2589             ClassSymbol c = cdef.sym;
2590             this.toplevel = env.toplevel;
2591             this.endPosTable = toplevel.endPositions;
2592             c.pool = pool;
2593             pool.reset();
2594             /* method normalizeDefs() can add references to external classes into the constant pool
2595              */
2596             cdef.defs = normalizeDefs(cdef.defs, c);
2597             generateReferencesToPrunedTree(c, pool);
2598             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
2599             localEnv.toplevel = env.toplevel;
2600             localEnv.enclClass = cdef;
2601 
2602             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2603                 genDef(l.head, localEnv);
2604             }
2605             if (pool.numEntries() > Pool.MAX_ENTRIES) {
2606                 log.error(cdef.pos(), "limit.pool");
2607                 nerrs++;
2608             }
2609             if (nerrs != 0) {
2610                 // if errors, discard code
2611                 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2612                     if (l.head.hasTag(METHODDEF))
2613                         ((JCMethodDecl) l.head).sym.code = null;
2614                 }
2615             }
2616             cdef.defs = List.nil(); // discard trees
2617             return nerrs == 0;
2618         } finally {
2619             // note: this method does NOT support recursion.
2620             attrEnv = null;
2621             this.env = null;
2622             toplevel = null;
2623             endPosTable = null;
2624             nerrs = 0;
2625         }
2626     }
2627 
2628 /* ************************************************************************
2629  * Auxiliary classes
2630  *************************************************************************/
2631 
2632     /** An abstract class for finalizer generation.
2633      */
2634     abstract class GenFinalizer {
2635         /** Generate code to clean up when unwinding. */
2636         abstract void gen();
2637 
2638         /** Generate code to clean up at last. */
2639         abstract void genLast();
2640 
2641         /** Does this finalizer have some nontrivial cleanup to perform? */
2642         boolean hasFinalizer() { return true; }
2643     }
2644 
2645     /** code generation contexts,
2646      *  to be used as type parameter for environments.
2647      */
2648     static class GenContext {
2649 
2650         /** A chain for all unresolved jumps that exit the current environment.
2651          */
2652         Chain exit = null;
2653 
2654         /** A chain for all unresolved jumps that continue in the
2655          *  current environment.
2656          */
2657         Chain cont = null;
2658 
2659         /** A closure that generates the finalizer of the current environment.
2660          *  Only set for Synchronized and Try contexts.
2661          */
2662         GenFinalizer finalize = null;
2663 
2664         /** Is this a switch statement?  If so, allocate registers
2665          * even when the variable declaration is unreachable.
2666          */
2667         boolean isSwitch = false;
2668 
2669         /** A list buffer containing all gaps in the finalizer range,
2670          *  where a catch all exception should not apply.
2671          */
2672         ListBuffer<Integer> gaps = null;
2673 
2674         /** Add given chain to exit chain.
2675          */
2676         void addExit(Chain c)  {
2677             exit = Code.mergeChains(c, exit);
2678         }
2679 
2680         /** Add given chain to cont chain.
2681          */
2682         void addCont(Chain c) {
2683             cont = Code.mergeChains(c, cont);
2684         }
2685     }
2686 
2687 }