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