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