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