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