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