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