Gen.java revision 3528:5538ba41cb97
1205821Sedwin/*
2205872Sedwin * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
3205872Sedwin * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4205821Sedwin *
5205821Sedwin * This code is free software; you can redistribute it and/or modify it
6205821Sedwin * under the terms of the GNU General Public License version 2 only, as
7205821Sedwin * published by the Free Software Foundation.  Oracle designates this
8205821Sedwin * particular file as subject to the "Classpath" exception as provided
9205821Sedwin * by Oracle in the LICENSE file that accompanied this code.
10205821Sedwin *
11205821Sedwin * This code is distributed in the hope that it will be useful, but WITHOUT
12205821Sedwin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13251647Sgrog * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14205821Sedwin * version 2 for more details (a copy is included in the LICENSE file that
15205821Sedwin * accompanied this code).
16205821Sedwin *
17205821Sedwin * You should have received a copy of the GNU General Public License version
18205821Sedwin * 2 along with this work; if not, write to the Free Software Foundation,
19205821Sedwin * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20205821Sedwin *
21205821Sedwin * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22205821Sedwin * or visit www.oracle.com if you need additional information or have any
23205821Sedwin * questions.
24205821Sedwin */
25251647Sgrog
26205821Sedwinpackage com.sun.tools.javac.jvm;
27205821Sedwin
28205821Sedwinimport com.sun.tools.javac.util.*;
29205821Sedwinimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
30205821Sedwinimport com.sun.tools.javac.util.List;
31205821Sedwinimport com.sun.tools.javac.code.*;
32205821Sedwinimport com.sun.tools.javac.code.Attribute.TypeCompound;
33205821Sedwinimport com.sun.tools.javac.code.Symbol.VarSymbol;
34205821Sedwinimport com.sun.tools.javac.comp.*;
35205821Sedwinimport com.sun.tools.javac.tree.*;
36205821Sedwin
37205821Sedwinimport com.sun.tools.javac.code.Symbol.*;
38205821Sedwinimport com.sun.tools.javac.code.Type.*;
39205821Sedwinimport com.sun.tools.javac.jvm.Code.*;
40205821Sedwinimport com.sun.tools.javac.jvm.Items.*;
41205821Sedwinimport com.sun.tools.javac.main.Option;
42205821Sedwinimport com.sun.tools.javac.tree.EndPosTable;
43205821Sedwinimport com.sun.tools.javac.tree.JCTree.*;
44205821Sedwin
45205821Sedwinimport static com.sun.tools.javac.code.Flags.*;
46205821Sedwinimport static com.sun.tools.javac.code.Kinds.Kind.*;
47205821Sedwinimport static com.sun.tools.javac.code.TypeTag.*;
48205821Sedwinimport static com.sun.tools.javac.jvm.ByteCodes.*;
49205821Sedwinimport static com.sun.tools.javac.jvm.CRTFlags.*;
50205821Sedwinimport static com.sun.tools.javac.main.Option.*;
51205821Sedwinimport static com.sun.tools.javac.tree.JCTree.Tag.*;
52205821Sedwin
53205821Sedwin/** This pass maps flat Java (i.e. without inner classes) to bytecodes.
54205821Sedwin *
55205821Sedwin *  <p><b>This is NOT part of any supported API.
56205821Sedwin *  If you write code that depends on this, you do so at your own risk.
57205821Sedwin *  This code and its internal interfaces are subject to change or
58205821Sedwin *  deletion without notice.</b>
59205821Sedwin */
60205821Sedwinpublic class Gen extends JCTree.Visitor {
61205821Sedwin    protected static final Context.Key<Gen> genKey = new Context.Key<>();
62205821Sedwin
63205821Sedwin    private final Log log;
64205821Sedwin    private final Symtab syms;
65205821Sedwin    private final Check chk;
66205821Sedwin    private final Resolve rs;
67205821Sedwin    private final TreeMaker make;
68205821Sedwin    private final Names names;
69205821Sedwin    private final Target target;
70205821Sedwin    private Name accessDollar;
71205821Sedwin    private final Types types;
72205821Sedwin    private final Lower lower;
73205821Sedwin    private final Flow flow;
74205821Sedwin    private final Annotate annotate;
75205821Sedwin    private final StringConcat concat;
76205821Sedwin
77205821Sedwin    /** Format of stackmap tables to be generated. */
78205821Sedwin    private final Code.StackMapFormat stackMap;
79205821Sedwin
80205821Sedwin    /** A type that serves as the expected type for all method expressions.
81205821Sedwin     */
82205821Sedwin    private final Type methodType;
83205821Sedwin
84205821Sedwin    /**
85205821Sedwin     * Are we presently traversing a let expression ? Yes if depth != 0
86205821Sedwin     */
87205821Sedwin    private int letExprDepth;
88205821Sedwin
89205821Sedwin    public static Gen instance(Context context) {
90205821Sedwin        Gen instance = context.get(genKey);
91205821Sedwin        if (instance == null)
92205821Sedwin            instance = new Gen(context);
93205821Sedwin        return instance;
94205821Sedwin    }
95205821Sedwin
96205821Sedwin    /** Constant pool, reset by genClass.
97205821Sedwin     */
98205821Sedwin    private Pool pool;
99205821Sedwin
100205821Sedwin    protected Gen(Context context) {
101205821Sedwin        context.put(genKey, this);
102205821Sedwin
103205821Sedwin        names = Names.instance(context);
104205821Sedwin        log = Log.instance(context);
105205821Sedwin        syms = Symtab.instance(context);
106205821Sedwin        chk = Check.instance(context);
107205821Sedwin        rs = Resolve.instance(context);
108205821Sedwin        make = TreeMaker.instance(context);
109205821Sedwin        target = Target.instance(context);
110205821Sedwin        types = Types.instance(context);
111205821Sedwin        concat = StringConcat.instance(context);
112205821Sedwin
113205821Sedwin        methodType = new MethodType(null, null, null, syms.methodClass);
114205821Sedwin        accessDollar = names.
115205821Sedwin            fromString("access" + target.syntheticNameChar());
116205821Sedwin        flow = Flow.instance(context);
117205821Sedwin        lower = Lower.instance(context);
118205821Sedwin
119205821Sedwin        Options options = Options.instance(context);
120205821Sedwin        lineDebugInfo =
121205821Sedwin            options.isUnset(G_CUSTOM) ||
122205821Sedwin            options.isSet(G_CUSTOM, "lines");
123205821Sedwin        varDebugInfo =
124205821Sedwin            options.isUnset(G_CUSTOM)
125205821Sedwin            ? options.isSet(G)
126205821Sedwin            : options.isSet(G_CUSTOM, "vars");
127205821Sedwin        genCrt = options.isSet(XJCOV);
128205821Sedwin        debugCode = options.isSet("debug.code");
129205821Sedwin        allowBetterNullChecks = target.hasObjects();
130205821Sedwin        pool = new Pool(types);
131205821Sedwin
132205821Sedwin        // ignore cldc because we cannot have both stackmap formats
133205821Sedwin        this.stackMap = StackMapFormat.JSR202;
134205821Sedwin        annotate = Annotate.instance(context);
135205821Sedwin    }
136205821Sedwin
137205821Sedwin    /** Switches
138205821Sedwin     */
139205821Sedwin    private final boolean lineDebugInfo;
140205821Sedwin    private final boolean varDebugInfo;
141205821Sedwin    private final boolean genCrt;
142205821Sedwin    private final boolean debugCode;
143205821Sedwin    private final boolean allowBetterNullChecks;
144205821Sedwin
145205821Sedwin    /** Code buffer, set by genMethod.
146205821Sedwin     */
147205821Sedwin    private Code code;
148205821Sedwin
149205821Sedwin    /** Items structure, set by genMethod.
150205821Sedwin     */
151205821Sedwin    private Items items;
152205821Sedwin
153205821Sedwin    /** Environment for symbol lookup, set by genClass
154205821Sedwin     */
155205821Sedwin    private Env<AttrContext> attrEnv;
156205821Sedwin
157205821Sedwin    /** The top level tree.
158205821Sedwin     */
159205821Sedwin    private JCCompilationUnit toplevel;
160205821Sedwin
161205821Sedwin    /** The number of code-gen errors in this class.
162205821Sedwin     */
163205821Sedwin    private int nerrs = 0;
164205821Sedwin
165205821Sedwin    /** An object containing mappings of syntax trees to their
166205821Sedwin     *  ending source positions.
167205821Sedwin     */
168205821Sedwin    EndPosTable endPosTable;
169205821Sedwin
170205821Sedwin    /** Generate code to load an integer constant.
171205821Sedwin     *  @param n     The integer to be loaded.
172205821Sedwin     */
173205821Sedwin    void loadIntConst(int n) {
174205821Sedwin        items.makeImmediateItem(syms.intType, n).load();
175205821Sedwin    }
176205821Sedwin
177205821Sedwin    /** The opcode that loads a zero constant of a given type code.
178205821Sedwin     *  @param tc   The given type code (@see ByteCode).
179205821Sedwin     */
180205821Sedwin    public static int zero(int tc) {
181205821Sedwin        switch(tc) {
182205821Sedwin        case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
183205821Sedwin            return iconst_0;
184205821Sedwin        case LONGcode:
185205821Sedwin            return lconst_0;
186205821Sedwin        case FLOATcode:
187205821Sedwin            return fconst_0;
188205821Sedwin        case DOUBLEcode:
189205821Sedwin            return dconst_0;
190205821Sedwin        default:
191205821Sedwin            throw new AssertionError("zero");
192205821Sedwin        }
193205821Sedwin    }
194205821Sedwin
195205821Sedwin    /** The opcode that loads a one constant of a given type code.
196205821Sedwin     *  @param tc   The given type code (@see ByteCode).
197205821Sedwin     */
198205821Sedwin    public static int one(int tc) {
199205821Sedwin        return zero(tc) + 1;
200205821Sedwin    }
201205821Sedwin
202205821Sedwin    /** Generate code to load -1 of the given type code (either int or long).
203205821Sedwin     *  @param tc   The given type code (@see ByteCode).
204205821Sedwin     */
205205821Sedwin    void emitMinusOne(int tc) {
206205821Sedwin        if (tc == LONGcode) {
207205821Sedwin            items.makeImmediateItem(syms.longType, Long.valueOf(-1)).load();
208205821Sedwin        } else {
209205821Sedwin            code.emitop0(iconst_m1);
210205821Sedwin        }
211205821Sedwin    }
212205821Sedwin
213205821Sedwin    /** Construct a symbol to reflect the qualifying type that should
214205821Sedwin     *  appear in the byte code as per JLS 13.1.
215205821Sedwin     *
216205821Sedwin     *  For {@literal target >= 1.2}: Clone a method with the qualifier as owner (except
217205821Sedwin     *  for those cases where we need to work around VM bugs).
218205821Sedwin     *
219205821Sedwin     *  For {@literal target <= 1.1}: If qualified variable or method is defined in a
220205821Sedwin     *  non-accessible class, clone it with the qualifier class as owner.
221205821Sedwin     *
222205821Sedwin     *  @param sym    The accessed symbol
223205821Sedwin     *  @param site   The qualifier's type.
224205821Sedwin     */
225205821Sedwin    Symbol binaryQualifier(Symbol sym, Type site) {
226205821Sedwin
227205821Sedwin        if (site.hasTag(ARRAY)) {
228205821Sedwin            if (sym == syms.lengthVar ||
229205821Sedwin                sym.owner != syms.arrayClass)
230208829Sedwin                return sym;
231205821Sedwin            // array clone can be qualified by the array type in later targets
232205821Sedwin            Symbol qualifier = new ClassSymbol(Flags.PUBLIC, site.tsym.name,
233205821Sedwin                                               site, syms.noSymbol);
234208829Sedwin            return sym.clone(qualifier);
235205821Sedwin        }
236205821Sedwin
237205821Sedwin        if (sym.owner == site.tsym ||
238205821Sedwin            (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
239205821Sedwin            return sym;
240205821Sedwin        }
241208829Sedwin
242208829Sedwin        // leave alone methods inherited from Object
243205821Sedwin        // JLS 13.1.
244205821Sedwin        if (sym.owner == syms.objectType.tsym)
245205821Sedwin            return sym;
246208829Sedwin
247205821Sedwin        return sym.clone(site.tsym);
248205821Sedwin    }
249205821Sedwin
250205821Sedwin    /** Insert a reference to given type in the constant pool,
251205821Sedwin     *  checking for an array with too many dimensions;
252205821Sedwin     *  return the reference's index.
253205821Sedwin     *  @param type   The type for which a reference is inserted.
254208829Sedwin     */
255208829Sedwin    int makeRef(DiagnosticPosition pos, Type type) {
256208829Sedwin        checkDimension(pos, type);
257205821Sedwin        if (type.isAnnotated()) {
258205821Sedwin            return pool.put((Object)type);
259205821Sedwin        } else {
260205821Sedwin            return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
261205821Sedwin        }
262205821Sedwin    }
263205821Sedwin
264205821Sedwin    /** Check if the given type is an array with too many dimensions.
265205821Sedwin     */
266205821Sedwin    private void checkDimension(DiagnosticPosition pos, Type t) {
267205821Sedwin        switch (t.getTag()) {
268205821Sedwin        case METHOD:
269208829Sedwin            checkDimension(pos, t.getReturnType());
270205821Sedwin            for (List<Type> args = t.getParameterTypes(); args.nonEmpty(); args = args.tail)
271205821Sedwin                checkDimension(pos, args.head);
272205821Sedwin            break;
273208829Sedwin        case ARRAY:
274205821Sedwin            if (types.dimensions(t) > ClassFile.MAX_DIMENSIONS) {
275205821Sedwin                log.error(pos, "limit.dimensions");
276205821Sedwin                nerrs++;
277205821Sedwin            }
278205821Sedwin            break;
279205821Sedwin        default:
280208829Sedwin            break;
281208829Sedwin        }
282205821Sedwin    }
283205821Sedwin
284205821Sedwin    /** Create a tempory variable.
285208829Sedwin     *  @param type   The variable's type.
286205821Sedwin     */
287205821Sedwin    LocalItem makeTemp(Type type) {
288205821Sedwin        VarSymbol v = new VarSymbol(Flags.SYNTHETIC,
289205821Sedwin                                    names.empty,
290205821Sedwin                                    type,
291205821Sedwin                                    env.enclMethod.sym);
292205821Sedwin        code.newLocal(v);
293208829Sedwin        return items.makeLocalItem(v);
294208829Sedwin    }
295208829Sedwin
296205821Sedwin    /** Generate code to call a non-private method or constructor.
297205821Sedwin     *  @param pos         Position to be used for error reporting.
298205821Sedwin     *  @param site        The type of which the method is a member.
299205821Sedwin     *  @param name        The method's name.
300205821Sedwin     *  @param argtypes    The method's argument types.
301205821Sedwin     *  @param isStatic    A flag that indicates whether we call a
302205821Sedwin     *                     static or instance method.
303205821Sedwin     */
304205821Sedwin    void callMethod(DiagnosticPosition pos,
305205821Sedwin                    Type site, Name name, List<Type> argtypes,
306205821Sedwin                    boolean isStatic) {
307205821Sedwin        Symbol msym = rs.
308205821Sedwin            resolveInternalMethod(pos, attrEnv, site, name, argtypes, null);
309205821Sedwin        if (isStatic) items.makeStaticItem(msym).invoke();
310205821Sedwin        else items.makeMemberItem(msym, name == names.init).invoke();
311205821Sedwin    }
312205821Sedwin
313205821Sedwin    /** Is the given method definition an access method
314205821Sedwin     *  resulting from a qualified super? This is signified by an odd
315205821Sedwin     *  access code.
316205821Sedwin     */
317205821Sedwin    private boolean isAccessSuper(JCMethodDecl enclMethod) {
318205821Sedwin        return
319205821Sedwin            (enclMethod.mods.flags & SYNTHETIC) != 0 &&
320205821Sedwin            isOddAccessName(enclMethod.name);
321205821Sedwin    }
322205821Sedwin
323205821Sedwin    /** Does given name start with "access$" and end in an odd digit?
324205821Sedwin     */
325205821Sedwin    private boolean isOddAccessName(Name name) {
326205821Sedwin        return
327205821Sedwin            name.startsWith(accessDollar) &&
328205821Sedwin            (name.getByteAt(name.getByteLength() - 1) & 1) == 1;
329205821Sedwin    }
330205821Sedwin
331205821Sedwin/* ************************************************************************
332205821Sedwin * Non-local exits
333205821Sedwin *************************************************************************/
334205821Sedwin
335205821Sedwin    /** Generate code to invoke the finalizer associated with given
336205821Sedwin     *  environment.
337205821Sedwin     *  Any calls to finalizers are appended to the environments `cont' chain.
338205821Sedwin     *  Mark beginning of gap in catch all range for finalizer.
339205821Sedwin     */
340205821Sedwin    void genFinalizer(Env<GenContext> env) {
341205821Sedwin        if (code.isAlive() && env.info.finalize != null)
342205821Sedwin            env.info.finalize.gen();
343205821Sedwin    }
344205821Sedwin
345205821Sedwin    /** Generate code to call all finalizers of structures aborted by
346205821Sedwin     *  a non-local
347205821Sedwin     *  exit.  Return target environment of the non-local exit.
348205821Sedwin     *  @param target      The tree representing the structure that's aborted
349205821Sedwin     *  @param env         The environment current at the non-local exit.
350205821Sedwin     */
351205821Sedwin    Env<GenContext> unwind(JCTree target, Env<GenContext> env) {
352205821Sedwin        Env<GenContext> env1 = env;
353205821Sedwin        while (true) {
354205821Sedwin            genFinalizer(env1);
355205821Sedwin            if (env1.tree == target) break;
356205821Sedwin            env1 = env1.next;
357205821Sedwin        }
358205821Sedwin        return env1;
359205821Sedwin    }
360205821Sedwin
361205821Sedwin    /** Mark end of gap in catch-all range for finalizer.
362205821Sedwin     *  @param env   the environment which might contain the finalizer
363205821Sedwin     *               (if it does, env.info.gaps != null).
364205821Sedwin     */
365205821Sedwin    void endFinalizerGap(Env<GenContext> env) {
366205821Sedwin        if (env.info.gaps != null && env.info.gaps.length() % 2 == 1)
367205821Sedwin            env.info.gaps.append(code.curCP());
368205821Sedwin    }
369205821Sedwin
370205821Sedwin    /** Mark end of all gaps in catch-all ranges for finalizers of environments
371205821Sedwin     *  lying between, and including to two environments.
372205821Sedwin     *  @param from    the most deeply nested environment to mark
373205821Sedwin     *  @param to      the least deeply nested environment to mark
374205821Sedwin     */
375205821Sedwin    void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {
376251647Sgrog        Env<GenContext> last = null;
377205821Sedwin        while (last != to) {
378205821Sedwin            endFinalizerGap(from);
379205821Sedwin            last = from;
380205821Sedwin            from = from.next;
381205821Sedwin        }
382205821Sedwin    }
383205821Sedwin
384205821Sedwin    /** Do any of the structures aborted by a non-local exit have
385205821Sedwin     *  finalizers that require an empty stack?
386205821Sedwin     *  @param target      The tree representing the structure that's aborted
387205821Sedwin     *  @param env         The environment current at the non-local exit.
388205821Sedwin     */
389205821Sedwin    boolean hasFinally(JCTree target, Env<GenContext> env) {
390205821Sedwin        while (env.tree != target) {
391205821Sedwin            if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
392205821Sedwin                return true;
393205821Sedwin            env = env.next;
394205821Sedwin        }
395205821Sedwin        return false;
396205821Sedwin    }
397205821Sedwin
398205821Sedwin/* ************************************************************************
399205821Sedwin * Normalizing class-members.
400205821Sedwin *************************************************************************/
401205821Sedwin
402205821Sedwin    /** Distribute member initializer code into constructors and {@code <clinit>}
403205821Sedwin     *  method.
404205821Sedwin     *  @param defs         The list of class member declarations.
405205821Sedwin     *  @param c            The enclosing class.
406205821Sedwin     */
407205821Sedwin    List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
408205821Sedwin        ListBuffer<JCStatement> initCode = new ListBuffer<>();
409205821Sedwin        ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
410205821Sedwin        ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
411205821Sedwin        ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
412205821Sedwin        ListBuffer<JCTree> methodDefs = new ListBuffer<>();
413205821Sedwin        // Sort definitions into three listbuffers:
414205821Sedwin        //  - initCode for instance initializers
415205821Sedwin        //  - clinitCode for class initializers
416205821Sedwin        //  - methodDefs for method definitions
417205821Sedwin        for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
418205821Sedwin            JCTree def = l.head;
419205821Sedwin            switch (def.getTag()) {
420205821Sedwin            case BLOCK:
421205821Sedwin                JCBlock block = (JCBlock)def;
422205821Sedwin                if ((block.flags & STATIC) != 0)
423205821Sedwin                    clinitCode.append(block);
424205821Sedwin                else if ((block.flags & SYNTHETIC) == 0)
425205821Sedwin                    initCode.append(block);
426205821Sedwin                break;
427205821Sedwin            case METHODDEF:
428205821Sedwin                methodDefs.append(def);
429205821Sedwin                break;
430205821Sedwin            case VARDEF:
431205821Sedwin                JCVariableDecl vdef = (JCVariableDecl) def;
432205821Sedwin                VarSymbol sym = vdef.sym;
433205821Sedwin                checkDimension(vdef.pos(), sym.type);
434205821Sedwin                if (vdef.init != null) {
435205821Sedwin                    if ((sym.flags() & STATIC) == 0) {
436205821Sedwin                        // Always initialize instance variables.
437205821Sedwin                        JCStatement init = make.at(vdef.pos()).
438205821Sedwin                            Assignment(sym, vdef.init);
439205821Sedwin                        initCode.append(init);
440205821Sedwin                        endPosTable.replaceTree(vdef, init);
441205821Sedwin                        initTAs.addAll(getAndRemoveNonFieldTAs(sym));
442205821Sedwin                    } else if (sym.getConstValue() == null) {
443205821Sedwin                        // Initialize class (static) variables only if
444205821Sedwin                        // they are not compile-time constants.
445205821Sedwin                        JCStatement init = make.at(vdef.pos).
446205821Sedwin                            Assignment(sym, vdef.init);
447205821Sedwin                        clinitCode.append(init);
448205821Sedwin                        endPosTable.replaceTree(vdef, init);
449                        clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
450                    } else {
451                        checkStringConstant(vdef.init.pos(), sym.getConstValue());
452                        /* if the init contains a reference to an external class, add it to the
453                         * constant's pool
454                         */
455                        vdef.init.accept(classReferenceVisitor);
456                    }
457                }
458                break;
459            default:
460                Assert.error();
461            }
462        }
463        // Insert any instance initializers into all constructors.
464        if (initCode.length() != 0) {
465            List<JCStatement> inits = initCode.toList();
466            initTAs.addAll(c.getInitTypeAttributes());
467            List<Attribute.TypeCompound> initTAlist = initTAs.toList();
468            for (JCTree t : methodDefs) {
469                normalizeMethod((JCMethodDecl)t, inits, initTAlist);
470            }
471        }
472        // If there are class initializers, create a <clinit> method
473        // that contains them as its body.
474        if (clinitCode.length() != 0) {
475            MethodSymbol clinit = new MethodSymbol(
476                STATIC | (c.flags() & STRICTFP),
477                names.clinit,
478                new MethodType(
479                    List.<Type>nil(), syms.voidType,
480                    List.<Type>nil(), syms.methodClass),
481                c);
482            c.members().enter(clinit);
483            List<JCStatement> clinitStats = clinitCode.toList();
484            JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
485            block.endpos = TreeInfo.endPos(clinitStats.last());
486            methodDefs.append(make.MethodDef(clinit, block));
487
488            if (!clinitTAs.isEmpty())
489                clinit.appendUniqueTypeAttributes(clinitTAs.toList());
490            if (!c.getClassInitTypeAttributes().isEmpty())
491                clinit.appendUniqueTypeAttributes(c.getClassInitTypeAttributes());
492        }
493        // Return all method definitions.
494        return methodDefs.toList();
495    }
496
497    private List<Attribute.TypeCompound> getAndRemoveNonFieldTAs(VarSymbol sym) {
498        List<TypeCompound> tas = sym.getRawTypeAttributes();
499        ListBuffer<Attribute.TypeCompound> fieldTAs = new ListBuffer<>();
500        ListBuffer<Attribute.TypeCompound> nonfieldTAs = new ListBuffer<>();
501        for (TypeCompound ta : tas) {
502            Assert.check(ta.getPosition().type != TargetType.UNKNOWN);
503            if (ta.getPosition().type == TargetType.FIELD) {
504                fieldTAs.add(ta);
505            } else {
506                nonfieldTAs.add(ta);
507            }
508        }
509        sym.setTypeAttributes(fieldTAs.toList());
510        return nonfieldTAs.toList();
511    }
512
513    /** Check a constant value and report if it is a string that is
514     *  too large.
515     */
516    private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
517        if (nerrs != 0 || // only complain about a long string once
518            constValue == null ||
519            !(constValue instanceof String) ||
520            ((String)constValue).length() < Pool.MAX_STRING_LENGTH)
521            return;
522        log.error(pos, "limit.string");
523        nerrs++;
524    }
525
526    /** Insert instance initializer code into initial constructor.
527     *  @param md        The tree potentially representing a
528     *                   constructor's definition.
529     *  @param initCode  The list of instance initializer statements.
530     *  @param initTAs  Type annotations from the initializer expression.
531     */
532    void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
533        if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
534            // We are seeing a constructor that does not call another
535            // constructor of the same class.
536            List<JCStatement> stats = md.body.stats;
537            ListBuffer<JCStatement> newstats = new ListBuffer<>();
538
539            if (stats.nonEmpty()) {
540                // Copy initializers of synthetic variables generated in
541                // the translation of inner classes.
542                while (TreeInfo.isSyntheticInit(stats.head)) {
543                    newstats.append(stats.head);
544                    stats = stats.tail;
545                }
546                // Copy superclass constructor call
547                newstats.append(stats.head);
548                stats = stats.tail;
549                // Copy remaining synthetic initializers.
550                while (stats.nonEmpty() &&
551                       TreeInfo.isSyntheticInit(stats.head)) {
552                    newstats.append(stats.head);
553                    stats = stats.tail;
554                }
555                // Now insert the initializer code.
556                newstats.appendList(initCode);
557                // And copy all remaining statements.
558                while (stats.nonEmpty()) {
559                    newstats.append(stats.head);
560                    stats = stats.tail;
561                }
562            }
563            md.body.stats = newstats.toList();
564            if (md.body.endpos == Position.NOPOS)
565                md.body.endpos = TreeInfo.endPos(md.body.stats.last());
566
567            md.sym.appendUniqueTypeAttributes(initTAs);
568        }
569    }
570
571/* ************************************************************************
572 * Traversal methods
573 *************************************************************************/
574
575    /** Visitor argument: The current environment.
576     */
577    Env<GenContext> env;
578
579    /** Visitor argument: The expected type (prototype).
580     */
581    Type pt;
582
583    /** Visitor result: The item representing the computed value.
584     */
585    Item result;
586
587    /** Visitor method: generate code for a definition, catching and reporting
588     *  any completion failures.
589     *  @param tree    The definition to be visited.
590     *  @param env     The environment current at the definition.
591     */
592    public void genDef(JCTree tree, Env<GenContext> env) {
593        Env<GenContext> prevEnv = this.env;
594        try {
595            this.env = env;
596            tree.accept(this);
597        } catch (CompletionFailure ex) {
598            chk.completionError(tree.pos(), ex);
599        } finally {
600            this.env = prevEnv;
601        }
602    }
603
604    /** Derived visitor method: check whether CharacterRangeTable
605     *  should be emitted, if so, put a new entry into CRTable
606     *  and call method to generate bytecode.
607     *  If not, just call method to generate bytecode.
608     *  @see    #genStat(JCTree, Env)
609     *
610     *  @param  tree     The tree to be visited.
611     *  @param  env      The environment to use.
612     *  @param  crtFlags The CharacterRangeTable flags
613     *                   indicating type of the entry.
614     */
615    public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {
616        if (!genCrt) {
617            genStat(tree, env);
618            return;
619        }
620        int startpc = code.curCP();
621        genStat(tree, env);
622        if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK;
623        code.crt.put(tree, crtFlags, startpc, code.curCP());
624    }
625
626    /** Derived visitor method: generate code for a statement.
627     */
628    public void genStat(JCTree tree, Env<GenContext> env) {
629        if (code.isAlive()) {
630            code.statBegin(tree.pos);
631            genDef(tree, env);
632        } else if (env.info.isSwitch && tree.hasTag(VARDEF)) {
633            // variables whose declarations are in a switch
634            // can be used even if the decl is unreachable.
635            code.newLocal(((JCVariableDecl) tree).sym);
636        }
637    }
638
639    /** Derived visitor method: check whether CharacterRangeTable
640     *  should be emitted, if so, put a new entry into CRTable
641     *  and call method to generate bytecode.
642     *  If not, just call method to generate bytecode.
643     *  @see    #genStats(List, Env)
644     *
645     *  @param  trees    The list of trees to be visited.
646     *  @param  env      The environment to use.
647     *  @param  crtFlags The CharacterRangeTable flags
648     *                   indicating type of the entry.
649     */
650    public void genStats(List<JCStatement> trees, Env<GenContext> env, int crtFlags) {
651        if (!genCrt) {
652            genStats(trees, env);
653            return;
654        }
655        if (trees.length() == 1) {        // mark one statement with the flags
656            genStat(trees.head, env, crtFlags | CRT_STATEMENT);
657        } else {
658            int startpc = code.curCP();
659            genStats(trees, env);
660            code.crt.put(trees, crtFlags, startpc, code.curCP());
661        }
662    }
663
664    /** Derived visitor method: generate code for a list of statements.
665     */
666    public void genStats(List<? extends JCTree> trees, Env<GenContext> env) {
667        for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
668            genStat(l.head, env, CRT_STATEMENT);
669    }
670
671    /** Derived visitor method: check whether CharacterRangeTable
672     *  should be emitted, if so, put a new entry into CRTable
673     *  and call method to generate bytecode.
674     *  If not, just call method to generate bytecode.
675     *  @see    #genCond(JCTree,boolean)
676     *
677     *  @param  tree     The tree to be visited.
678     *  @param  crtFlags The CharacterRangeTable flags
679     *                   indicating type of the entry.
680     */
681    public CondItem genCond(JCTree tree, int crtFlags) {
682        if (!genCrt) return genCond(tree, false);
683        int startpc = code.curCP();
684        CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);
685        code.crt.put(tree, crtFlags, startpc, code.curCP());
686        return item;
687    }
688
689    /** Derived visitor method: generate code for a boolean
690     *  expression in a control-flow context.
691     *  @param _tree         The expression to be visited.
692     *  @param markBranches The flag to indicate that the condition is
693     *                      a flow controller so produced conditions
694     *                      should contain a proper tree to generate
695     *                      CharacterRangeTable branches for them.
696     */
697    public CondItem genCond(JCTree _tree, boolean markBranches) {
698        JCTree inner_tree = TreeInfo.skipParens(_tree);
699        if (inner_tree.hasTag(CONDEXPR)) {
700            JCConditional tree = (JCConditional)inner_tree;
701            CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
702            if (cond.isTrue()) {
703                code.resolve(cond.trueJumps);
704                CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);
705                if (markBranches) result.tree = tree.truepart;
706                return result;
707            }
708            if (cond.isFalse()) {
709                code.resolve(cond.falseJumps);
710                CondItem result = genCond(tree.falsepart, CRT_FLOW_TARGET);
711                if (markBranches) result.tree = tree.falsepart;
712                return result;
713            }
714            Chain secondJumps = cond.jumpFalse();
715            code.resolve(cond.trueJumps);
716            CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
717            if (markBranches) first.tree = tree.truepart;
718            Chain falseJumps = first.jumpFalse();
719            code.resolve(first.trueJumps);
720            Chain trueJumps = code.branch(goto_);
721            code.resolve(secondJumps);
722            CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);
723            CondItem result = items.makeCondItem(second.opcode,
724                                      Code.mergeChains(trueJumps, second.trueJumps),
725                                      Code.mergeChains(falseJumps, second.falseJumps));
726            if (markBranches) result.tree = tree.falsepart;
727            return result;
728        } else {
729            CondItem result = genExpr(_tree, syms.booleanType).mkCond();
730            if (markBranches) result.tree = _tree;
731            return result;
732        }
733    }
734
735    public Code getCode() {
736        return code;
737    }
738
739    public Items getItems() {
740        return items;
741    }
742
743    public Env<AttrContext> getAttrEnv() {
744        return attrEnv;
745    }
746
747    /** Visitor class for expressions which might be constant expressions.
748     *  This class is a subset of TreeScanner. Intended to visit trees pruned by
749     *  Lower as long as constant expressions looking for references to any
750     *  ClassSymbol. Any such reference will be added to the constant pool so
751     *  automated tools can detect class dependencies better.
752     */
753    class ClassReferenceVisitor extends JCTree.Visitor {
754
755        @Override
756        public void visitTree(JCTree tree) {}
757
758        @Override
759        public void visitBinary(JCBinary tree) {
760            tree.lhs.accept(this);
761            tree.rhs.accept(this);
762        }
763
764        @Override
765        public void visitSelect(JCFieldAccess tree) {
766            if (tree.selected.type.hasTag(CLASS)) {
767                makeRef(tree.selected.pos(), tree.selected.type);
768            }
769        }
770
771        @Override
772        public void visitIdent(JCIdent tree) {
773            if (tree.sym.owner instanceof ClassSymbol) {
774                pool.put(tree.sym.owner);
775            }
776        }
777
778        @Override
779        public void visitConditional(JCConditional tree) {
780            tree.cond.accept(this);
781            tree.truepart.accept(this);
782            tree.falsepart.accept(this);
783        }
784
785        @Override
786        public void visitUnary(JCUnary tree) {
787            tree.arg.accept(this);
788        }
789
790        @Override
791        public void visitParens(JCParens tree) {
792            tree.expr.accept(this);
793        }
794
795        @Override
796        public void visitTypeCast(JCTypeCast tree) {
797            tree.expr.accept(this);
798        }
799    }
800
801    private ClassReferenceVisitor classReferenceVisitor = new ClassReferenceVisitor();
802
803    /** Visitor method: generate code for an expression, catching and reporting
804     *  any completion failures.
805     *  @param tree    The expression to be visited.
806     *  @param pt      The expression's expected type (proto-type).
807     */
808    public Item genExpr(JCTree tree, Type pt) {
809        Type prevPt = this.pt;
810        try {
811            if (tree.type.constValue() != null) {
812                // Short circuit any expressions which are constants
813                tree.accept(classReferenceVisitor);
814                checkStringConstant(tree.pos(), tree.type.constValue());
815                result = items.makeImmediateItem(tree.type, tree.type.constValue());
816            } else {
817                this.pt = pt;
818                tree.accept(this);
819            }
820            return result.coerce(pt);
821        } catch (CompletionFailure ex) {
822            chk.completionError(tree.pos(), ex);
823            code.state.stacksize = 1;
824            return items.makeStackItem(pt);
825        } finally {
826            this.pt = prevPt;
827        }
828    }
829
830    /** Derived visitor method: generate code for a list of method arguments.
831     *  @param trees    The argument expressions to be visited.
832     *  @param pts      The expression's expected types (i.e. the formal parameter
833     *                  types of the invoked method).
834     */
835    public void genArgs(List<JCExpression> trees, List<Type> pts) {
836        for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) {
837            genExpr(l.head, pts.head).load();
838            pts = pts.tail;
839        }
840        // require lists be of same length
841        Assert.check(pts.isEmpty());
842    }
843
844/* ************************************************************************
845 * Visitor methods for statements and definitions
846 *************************************************************************/
847
848    /** Thrown when the byte code size exceeds limit.
849     */
850    public static class CodeSizeOverflow extends RuntimeException {
851        private static final long serialVersionUID = 0;
852        public CodeSizeOverflow() {}
853    }
854
855    public void visitMethodDef(JCMethodDecl tree) {
856        // Create a new local environment that points pack at method
857        // definition.
858        Env<GenContext> localEnv = env.dup(tree);
859        localEnv.enclMethod = tree;
860        // The expected type of every return statement in this method
861        // is the method's return type.
862        this.pt = tree.sym.erasure(types).getReturnType();
863
864        checkDimension(tree.pos(), tree.sym.erasure(types));
865        genMethod(tree, localEnv, false);
866    }
867//where
868        /** Generate code for a method.
869         *  @param tree     The tree representing the method definition.
870         *  @param env      The environment current for the method body.
871         *  @param fatcode  A flag that indicates whether all jumps are
872         *                  within 32K.  We first invoke this method under
873         *                  the assumption that fatcode == false, i.e. all
874         *                  jumps are within 32K.  If this fails, fatcode
875         *                  is set to true and we try again.
876         */
877        void genMethod(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
878            MethodSymbol meth = tree.sym;
879            int extras = 0;
880            // Count up extra parameters
881            if (meth.isConstructor()) {
882                extras++;
883                if (meth.enclClass().isInner() &&
884                    !meth.enclClass().isStatic()) {
885                    extras++;
886                }
887            } else if ((tree.mods.flags & STATIC) == 0) {
888                extras++;
889            }
890            //      System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG
891            if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) + extras >
892                ClassFile.MAX_PARAMETERS) {
893                log.error(tree.pos(), "limit.parameters");
894                nerrs++;
895            }
896
897            else if (tree.body != null) {
898                // Create a new code structure and initialize it.
899                int startpcCrt = initCode(tree, env, fatcode);
900
901                try {
902                    genStat(tree.body, env);
903                } catch (CodeSizeOverflow e) {
904                    // Failed due to code limit, try again with jsr/ret
905                    startpcCrt = initCode(tree, env, fatcode);
906                    genStat(tree.body, env);
907                }
908
909                if (code.state.stacksize != 0) {
910                    log.error(tree.body.pos(), "stack.sim.error", tree);
911                    throw new AssertionError();
912                }
913
914                // If last statement could complete normally, insert a
915                // return at the end.
916                if (code.isAlive()) {
917                    code.statBegin(TreeInfo.endPos(tree.body));
918                    if (env.enclMethod == null ||
919                        env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
920                        code.emitop0(return_);
921                    } else {
922                        // sometime dead code seems alive (4415991);
923                        // generate a small loop instead
924                        int startpc = code.entryPoint();
925                        CondItem c = items.makeCondItem(goto_);
926                        code.resolve(c.jumpTrue(), startpc);
927                    }
928                }
929                if (genCrt)
930                    code.crt.put(tree.body,
931                                 CRT_BLOCK,
932                                 startpcCrt,
933                                 code.curCP());
934
935                code.endScopes(0);
936
937                // If we exceeded limits, panic
938                if (code.checkLimits(tree.pos(), log)) {
939                    nerrs++;
940                    return;
941                }
942
943                // If we generated short code but got a long jump, do it again
944                // with fatCode = true.
945                if (!fatcode && code.fatcode) genMethod(tree, env, true);
946
947                // Clean up
948                if(stackMap == StackMapFormat.JSR202) {
949                    code.lastFrame = null;
950                    code.frameBeforeLast = null;
951                }
952
953                // Compress exception table
954                code.compressCatchTable();
955
956                // Fill in type annotation positions for exception parameters
957                code.fillExceptionParameterPositions();
958            }
959        }
960
961        private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
962            MethodSymbol meth = tree.sym;
963
964            // Create a new code structure.
965            meth.code = code = new Code(meth,
966                                        fatcode,
967                                        lineDebugInfo ? toplevel.lineMap : null,
968                                        varDebugInfo,
969                                        stackMap,
970                                        debugCode,
971                                        genCrt ? new CRTable(tree, env.toplevel.endPositions)
972                                               : null,
973                                        syms,
974                                        types,
975                                        pool);
976            items = new Items(pool, code, syms, types);
977            if (code.debugCode) {
978                System.err.println(meth + " for body " + tree);
979            }
980
981            // If method is not static, create a new local variable address
982            // for `this'.
983            if ((tree.mods.flags & STATIC) == 0) {
984                Type selfType = meth.owner.type;
985                if (meth.isConstructor() && selfType != syms.objectType)
986                    selfType = UninitializedType.uninitializedThis(selfType);
987                code.setDefined(
988                        code.newLocal(
989                            new VarSymbol(FINAL, names._this, selfType, meth.owner)));
990            }
991
992            // Mark all parameters as defined from the beginning of
993            // the method.
994            for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
995                checkDimension(l.head.pos(), l.head.sym.type);
996                code.setDefined(code.newLocal(l.head.sym));
997            }
998
999            // Get ready to generate code for method body.
1000            int startpcCrt = genCrt ? code.curCP() : 0;
1001            code.entryPoint();
1002
1003            // Suppress initial stackmap
1004            code.pendingStackMap = false;
1005
1006            return startpcCrt;
1007        }
1008
1009    public void visitVarDef(JCVariableDecl tree) {
1010        VarSymbol v = tree.sym;
1011        code.newLocal(v);
1012        if (tree.init != null) {
1013            checkStringConstant(tree.init.pos(), v.getConstValue());
1014            if (v.getConstValue() == null || varDebugInfo) {
1015                Assert.check(letExprDepth != 0 || code.state.stacksize == 0);
1016                genExpr(tree.init, v.erasure(types)).load();
1017                items.makeLocalItem(v).store();
1018                Assert.check(letExprDepth != 0 || code.state.stacksize == 0);
1019            }
1020        }
1021        checkDimension(tree.pos(), v.type);
1022    }
1023
1024    public void visitSkip(JCSkip tree) {
1025    }
1026
1027    public void visitBlock(JCBlock tree) {
1028        int limit = code.nextreg;
1029        Env<GenContext> localEnv = env.dup(tree, new GenContext());
1030        genStats(tree.stats, localEnv);
1031        // End the scope of all block-local variables in variable info.
1032        if (!env.tree.hasTag(METHODDEF)) {
1033            code.statBegin(tree.endpos);
1034            code.endScopes(limit);
1035            code.pendingStatPos = Position.NOPOS;
1036        }
1037    }
1038
1039    public void visitDoLoop(JCDoWhileLoop tree) {
1040        genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), false);
1041    }
1042
1043    public void visitWhileLoop(JCWhileLoop tree) {
1044        genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), true);
1045    }
1046
1047    public void visitForLoop(JCForLoop tree) {
1048        int limit = code.nextreg;
1049        genStats(tree.init, env);
1050        genLoop(tree, tree.body, tree.cond, tree.step, true);
1051        code.endScopes(limit);
1052    }
1053    //where
1054        /** Generate code for a loop.
1055         *  @param loop       The tree representing the loop.
1056         *  @param body       The loop's body.
1057         *  @param cond       The loop's controling condition.
1058         *  @param step       "Step" statements to be inserted at end of
1059         *                    each iteration.
1060         *  @param testFirst  True if the loop test belongs before the body.
1061         */
1062        private void genLoop(JCStatement loop,
1063                             JCStatement body,
1064                             JCExpression cond,
1065                             List<JCExpressionStatement> step,
1066                             boolean testFirst) {
1067            Env<GenContext> loopEnv = env.dup(loop, new GenContext());
1068            int startpc = code.entryPoint();
1069            if (testFirst) { //while or for loop
1070                CondItem c;
1071                if (cond != null) {
1072                    code.statBegin(cond.pos);
1073                    Assert.check(code.state.stacksize == 0);
1074                    c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1075                } else {
1076                    c = items.makeCondItem(goto_);
1077                }
1078                Chain loopDone = c.jumpFalse();
1079                code.resolve(c.trueJumps);
1080                Assert.check(code.state.stacksize == 0);
1081                genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1082                code.resolve(loopEnv.info.cont);
1083                genStats(step, loopEnv);
1084                code.resolve(code.branch(goto_), startpc);
1085                code.resolve(loopDone);
1086            } else {
1087                genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1088                code.resolve(loopEnv.info.cont);
1089                genStats(step, loopEnv);
1090                if (code.isAlive()) {
1091                    CondItem c;
1092                    if (cond != null) {
1093                        code.statBegin(cond.pos);
1094                        Assert.check(code.state.stacksize == 0);
1095                        c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1096                    } else {
1097                        c = items.makeCondItem(goto_);
1098                    }
1099                    code.resolve(c.jumpTrue(), startpc);
1100                    Assert.check(code.state.stacksize == 0);
1101                    code.resolve(c.falseJumps);
1102                }
1103            }
1104            Chain exit = loopEnv.info.exit;
1105            if (exit != null) {
1106                code.resolve(exit);
1107                exit.state.defined.excludeFrom(code.nextreg);
1108            }
1109        }
1110
1111    public void visitForeachLoop(JCEnhancedForLoop tree) {
1112        throw new AssertionError(); // should have been removed by Lower.
1113    }
1114
1115    public void visitLabelled(JCLabeledStatement tree) {
1116        Env<GenContext> localEnv = env.dup(tree, new GenContext());
1117        genStat(tree.body, localEnv, CRT_STATEMENT);
1118        Chain exit = localEnv.info.exit;
1119        if (exit != null) {
1120            code.resolve(exit);
1121            exit.state.defined.excludeFrom(code.nextreg);
1122        }
1123    }
1124
1125    public void visitSwitch(JCSwitch tree) {
1126        int limit = code.nextreg;
1127        Assert.check(!tree.selector.type.hasTag(CLASS));
1128        int startpcCrt = genCrt ? code.curCP() : 0;
1129        Assert.check(code.state.stacksize == 0);
1130        Item sel = genExpr(tree.selector, syms.intType);
1131        List<JCCase> cases = tree.cases;
1132        if (cases.isEmpty()) {
1133            // We are seeing:  switch <sel> {}
1134            sel.load().drop();
1135            if (genCrt)
1136                code.crt.put(TreeInfo.skipParens(tree.selector),
1137                             CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1138        } else {
1139            // We are seeing a nonempty switch.
1140            sel.load();
1141            if (genCrt)
1142                code.crt.put(TreeInfo.skipParens(tree.selector),
1143                             CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1144            Env<GenContext> switchEnv = env.dup(tree, new GenContext());
1145            switchEnv.info.isSwitch = true;
1146
1147            // Compute number of labels and minimum and maximum label values.
1148            // For each case, store its label in an array.
1149            int lo = Integer.MAX_VALUE;  // minimum label.
1150            int hi = Integer.MIN_VALUE;  // maximum label.
1151            int nlabels = 0;               // number of labels.
1152
1153            int[] labels = new int[cases.length()];  // the label array.
1154            int defaultIndex = -1;     // the index of the default clause.
1155
1156            List<JCCase> l = cases;
1157            for (int i = 0; i < labels.length; i++) {
1158                if (l.head.pat != null) {
1159                    int val = ((Number)l.head.pat.type.constValue()).intValue();
1160                    labels[i] = val;
1161                    if (val < lo) lo = val;
1162                    if (hi < val) hi = val;
1163                    nlabels++;
1164                } else {
1165                    Assert.check(defaultIndex == -1);
1166                    defaultIndex = i;
1167                }
1168                l = l.tail;
1169            }
1170
1171            // Determine whether to issue a tableswitch or a lookupswitch
1172            // instruction.
1173            long table_space_cost = 4 + ((long) hi - lo + 1); // words
1174            long table_time_cost = 3; // comparisons
1175            long lookup_space_cost = 3 + 2 * (long) nlabels;
1176            long lookup_time_cost = nlabels;
1177            int opcode =
1178                nlabels > 0 &&
1179                table_space_cost + 3 * table_time_cost <=
1180                lookup_space_cost + 3 * lookup_time_cost
1181                ?
1182                tableswitch : lookupswitch;
1183
1184            int startpc = code.curCP();    // the position of the selector operation
1185            code.emitop0(opcode);
1186            code.align(4);
1187            int tableBase = code.curCP();  // the start of the jump table
1188            int[] offsets = null;          // a table of offsets for a lookupswitch
1189            code.emit4(-1);                // leave space for default offset
1190            if (opcode == tableswitch) {
1191                code.emit4(lo);            // minimum label
1192                code.emit4(hi);            // maximum label
1193                for (long i = lo; i <= hi; i++) {  // leave space for jump table
1194                    code.emit4(-1);
1195                }
1196            } else {
1197                code.emit4(nlabels);    // number of labels
1198                for (int i = 0; i < nlabels; i++) {
1199                    code.emit4(-1); code.emit4(-1); // leave space for lookup table
1200                }
1201                offsets = new int[labels.length];
1202            }
1203            Code.State stateSwitch = code.state.dup();
1204            code.markDead();
1205
1206            // For each case do:
1207            l = cases;
1208            for (int i = 0; i < labels.length; i++) {
1209                JCCase c = l.head;
1210                l = l.tail;
1211
1212                int pc = code.entryPoint(stateSwitch);
1213                // Insert offset directly into code or else into the
1214                // offsets table.
1215                if (i != defaultIndex) {
1216                    if (opcode == tableswitch) {
1217                        code.put4(
1218                            tableBase + 4 * (labels[i] - lo + 3),
1219                            pc - startpc);
1220                    } else {
1221                        offsets[i] = pc - startpc;
1222                    }
1223                } else {
1224                    code.put4(tableBase, pc - startpc);
1225                }
1226
1227                // Generate code for the statements in this case.
1228                genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
1229            }
1230
1231            // Resolve all breaks.
1232            Chain exit = switchEnv.info.exit;
1233            if  (exit != null) {
1234                code.resolve(exit);
1235                exit.state.defined.excludeFrom(code.nextreg);
1236            }
1237
1238            // If we have not set the default offset, we do so now.
1239            if (code.get4(tableBase) == -1) {
1240                code.put4(tableBase, code.entryPoint(stateSwitch) - startpc);
1241            }
1242
1243            if (opcode == tableswitch) {
1244                // Let any unfilled slots point to the default case.
1245                int defaultOffset = code.get4(tableBase);
1246                for (long i = lo; i <= hi; i++) {
1247                    int t = (int)(tableBase + 4 * (i - lo + 3));
1248                    if (code.get4(t) == -1)
1249                        code.put4(t, defaultOffset);
1250                }
1251            } else {
1252                // Sort non-default offsets and copy into lookup table.
1253                if (defaultIndex >= 0)
1254                    for (int i = defaultIndex; i < labels.length - 1; i++) {
1255                        labels[i] = labels[i+1];
1256                        offsets[i] = offsets[i+1];
1257                    }
1258                if (nlabels > 0)
1259                    qsort2(labels, offsets, 0, nlabels - 1);
1260                for (int i = 0; i < nlabels; i++) {
1261                    int caseidx = tableBase + 8 * (i + 1);
1262                    code.put4(caseidx, labels[i]);
1263                    code.put4(caseidx + 4, offsets[i]);
1264                }
1265            }
1266        }
1267        code.endScopes(limit);
1268    }
1269//where
1270        /** Sort (int) arrays of keys and values
1271         */
1272       static void qsort2(int[] keys, int[] values, int lo, int hi) {
1273            int i = lo;
1274            int j = hi;
1275            int pivot = keys[(i+j)/2];
1276            do {
1277                while (keys[i] < pivot) i++;
1278                while (pivot < keys[j]) j--;
1279                if (i <= j) {
1280                    int temp1 = keys[i];
1281                    keys[i] = keys[j];
1282                    keys[j] = temp1;
1283                    int temp2 = values[i];
1284                    values[i] = values[j];
1285                    values[j] = temp2;
1286                    i++;
1287                    j--;
1288                }
1289            } while (i <= j);
1290            if (lo < j) qsort2(keys, values, lo, j);
1291            if (i < hi) qsort2(keys, values, i, hi);
1292        }
1293
1294    public void visitSynchronized(JCSynchronized tree) {
1295        int limit = code.nextreg;
1296        // Generate code to evaluate lock and save in temporary variable.
1297        final LocalItem lockVar = makeTemp(syms.objectType);
1298        Assert.check(code.state.stacksize == 0);
1299        genExpr(tree.lock, tree.lock.type).load().duplicate();
1300        lockVar.store();
1301
1302        // Generate code to enter monitor.
1303        code.emitop0(monitorenter);
1304        code.state.lock(lockVar.reg);
1305
1306        // Generate code for a try statement with given body, no catch clauses
1307        // in a new environment with the "exit-monitor" operation as finalizer.
1308        final Env<GenContext> syncEnv = env.dup(tree, new GenContext());
1309        syncEnv.info.finalize = new GenFinalizer() {
1310            void gen() {
1311                genLast();
1312                Assert.check(syncEnv.info.gaps.length() % 2 == 0);
1313                syncEnv.info.gaps.append(code.curCP());
1314            }
1315            void genLast() {
1316                if (code.isAlive()) {
1317                    lockVar.load();
1318                    code.emitop0(monitorexit);
1319                    code.state.unlock(lockVar.reg);
1320                }
1321            }
1322        };
1323        syncEnv.info.gaps = new ListBuffer<>();
1324        genTry(tree.body, List.<JCCatch>nil(), syncEnv);
1325        code.endScopes(limit);
1326    }
1327
1328    public void visitTry(final JCTry tree) {
1329        // Generate code for a try statement with given body and catch clauses,
1330        // in a new environment which calls the finally block if there is one.
1331        final Env<GenContext> tryEnv = env.dup(tree, new GenContext());
1332        final Env<GenContext> oldEnv = env;
1333        tryEnv.info.finalize = new GenFinalizer() {
1334            void gen() {
1335                Assert.check(tryEnv.info.gaps.length() % 2 == 0);
1336                tryEnv.info.gaps.append(code.curCP());
1337                genLast();
1338            }
1339            void genLast() {
1340                if (tree.finalizer != null)
1341                    genStat(tree.finalizer, oldEnv, CRT_BLOCK);
1342            }
1343            boolean hasFinalizer() {
1344                return tree.finalizer != null;
1345            }
1346        };
1347        tryEnv.info.gaps = new ListBuffer<>();
1348        genTry(tree.body, tree.catchers, tryEnv);
1349    }
1350    //where
1351        /** Generate code for a try or synchronized statement
1352         *  @param body      The body of the try or synchronized statement.
1353         *  @param catchers  The lis of catch clauses.
1354         *  @param env       the environment current for the body.
1355         */
1356        void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {
1357            int limit = code.nextreg;
1358            int startpc = code.curCP();
1359            Code.State stateTry = code.state.dup();
1360            genStat(body, env, CRT_BLOCK);
1361            int endpc = code.curCP();
1362            boolean hasFinalizer =
1363                env.info.finalize != null &&
1364                env.info.finalize.hasFinalizer();
1365            List<Integer> gaps = env.info.gaps.toList();
1366            code.statBegin(TreeInfo.endPos(body));
1367            genFinalizer(env);
1368            code.statBegin(TreeInfo.endPos(env.tree));
1369            Chain exitChain = code.branch(goto_);
1370            endFinalizerGap(env);
1371            if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
1372                // start off with exception on stack
1373                code.entryPoint(stateTry, l.head.param.sym.type);
1374                genCatch(l.head, env, startpc, endpc, gaps);
1375                genFinalizer(env);
1376                if (hasFinalizer || l.tail.nonEmpty()) {
1377                    code.statBegin(TreeInfo.endPos(env.tree));
1378                    exitChain = Code.mergeChains(exitChain,
1379                                                 code.branch(goto_));
1380                }
1381                endFinalizerGap(env);
1382            }
1383            if (hasFinalizer) {
1384                // Create a new register segement to avoid allocating
1385                // the same variables in finalizers and other statements.
1386                code.newRegSegment();
1387
1388                // Add a catch-all clause.
1389
1390                // start off with exception on stack
1391                int catchallpc = code.entryPoint(stateTry, syms.throwableType);
1392
1393                // Register all exception ranges for catch all clause.
1394                // The range of the catch all clause is from the beginning
1395                // of the try or synchronized block until the present
1396                // code pointer excluding all gaps in the current
1397                // environment's GenContext.
1398                int startseg = startpc;
1399                while (env.info.gaps.nonEmpty()) {
1400                    int endseg = env.info.gaps.next().intValue();
1401                    registerCatch(body.pos(), startseg, endseg,
1402                                  catchallpc, 0);
1403                    startseg = env.info.gaps.next().intValue();
1404                }
1405                code.statBegin(TreeInfo.finalizerPos(env.tree));
1406                code.markStatBegin();
1407
1408                Item excVar = makeTemp(syms.throwableType);
1409                excVar.store();
1410                genFinalizer(env);
1411                excVar.load();
1412                registerCatch(body.pos(), startseg,
1413                              env.info.gaps.next().intValue(),
1414                              catchallpc, 0);
1415                code.emitop0(athrow);
1416                code.markDead();
1417
1418                // If there are jsr's to this finalizer, ...
1419                if (env.info.cont != null) {
1420                    // Resolve all jsr's.
1421                    code.resolve(env.info.cont);
1422
1423                    // Mark statement line number
1424                    code.statBegin(TreeInfo.finalizerPos(env.tree));
1425                    code.markStatBegin();
1426
1427                    // Save return address.
1428                    LocalItem retVar = makeTemp(syms.throwableType);
1429                    retVar.store();
1430
1431                    // Generate finalizer code.
1432                    env.info.finalize.genLast();
1433
1434                    // Return.
1435                    code.emitop1w(ret, retVar.reg);
1436                    code.markDead();
1437                }
1438            }
1439            // Resolve all breaks.
1440            code.resolve(exitChain);
1441
1442            code.endScopes(limit);
1443        }
1444
1445        /** Generate code for a catch clause.
1446         *  @param tree     The catch clause.
1447         *  @param env      The environment current in the enclosing try.
1448         *  @param startpc  Start pc of try-block.
1449         *  @param endpc    End pc of try-block.
1450         */
1451        void genCatch(JCCatch tree,
1452                      Env<GenContext> env,
1453                      int startpc, int endpc,
1454                      List<Integer> gaps) {
1455            if (startpc != endpc) {
1456                List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypeExprs
1457                        = catchTypesWithAnnotations(tree);
1458                while (gaps.nonEmpty()) {
1459                    for (Pair<List<Attribute.TypeCompound>, JCExpression> subCatch1 : catchTypeExprs) {
1460                        JCExpression subCatch = subCatch1.snd;
1461                        int catchType = makeRef(tree.pos(), subCatch.type);
1462                        int end = gaps.head.intValue();
1463                        registerCatch(tree.pos(),
1464                                      startpc,  end, code.curCP(),
1465                                      catchType);
1466                        for (Attribute.TypeCompound tc :  subCatch1.fst) {
1467                                tc.position.setCatchInfo(catchType, startpc);
1468                        }
1469                    }
1470                    gaps = gaps.tail;
1471                    startpc = gaps.head.intValue();
1472                    gaps = gaps.tail;
1473                }
1474                if (startpc < endpc) {
1475                    for (Pair<List<Attribute.TypeCompound>, JCExpression> subCatch1 : catchTypeExprs) {
1476                        JCExpression subCatch = subCatch1.snd;
1477                        int catchType = makeRef(tree.pos(), subCatch.type);
1478                        registerCatch(tree.pos(),
1479                                      startpc, endpc, code.curCP(),
1480                                      catchType);
1481                        for (Attribute.TypeCompound tc :  subCatch1.fst) {
1482                            tc.position.setCatchInfo(catchType, startpc);
1483                        }
1484                    }
1485                }
1486                VarSymbol exparam = tree.param.sym;
1487                code.statBegin(tree.pos);
1488                code.markStatBegin();
1489                int limit = code.nextreg;
1490                code.newLocal(exparam);
1491                items.makeLocalItem(exparam).store();
1492                code.statBegin(TreeInfo.firstStatPos(tree.body));
1493                genStat(tree.body, env, CRT_BLOCK);
1494                code.endScopes(limit);
1495                code.statBegin(TreeInfo.endPos(tree.body));
1496            }
1497        }
1498        // where
1499        List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypesWithAnnotations(JCCatch tree) {
1500            return TreeInfo.isMultiCatch(tree) ?
1501                    catchTypesWithAnnotationsFromMulticatch((JCTypeUnion)tree.param.vartype, tree.param.sym.getRawTypeAttributes()) :
1502                    List.of(new Pair<>(tree.param.sym.getRawTypeAttributes(), tree.param.vartype));
1503        }
1504        // where
1505        List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypesWithAnnotationsFromMulticatch(JCTypeUnion tree, List<TypeCompound> first) {
1506            List<JCExpression> alts = tree.alternatives;
1507            List<Pair<List<TypeCompound>, JCExpression>> res = List.of(new Pair<>(first, alts.head));
1508            alts = alts.tail;
1509
1510            while(alts != null && alts.head != null) {
1511                JCExpression alt = alts.head;
1512                if (alt instanceof JCAnnotatedType) {
1513                    JCAnnotatedType a = (JCAnnotatedType)alt;
1514                    res = res.prepend(new Pair<>(annotate.fromAnnotations(a.annotations), alt));
1515                } else {
1516                    res = res.prepend(new Pair<>(List.nil(), alt));
1517                }
1518                alts = alts.tail;
1519            }
1520            return res.reverse();
1521        }
1522
1523        /** Register a catch clause in the "Exceptions" code-attribute.
1524         */
1525        void registerCatch(DiagnosticPosition pos,
1526                           int startpc, int endpc,
1527                           int handler_pc, int catch_type) {
1528            char startpc1 = (char)startpc;
1529            char endpc1 = (char)endpc;
1530            char handler_pc1 = (char)handler_pc;
1531            if (startpc1 == startpc &&
1532                endpc1 == endpc &&
1533                handler_pc1 == handler_pc) {
1534                code.addCatch(startpc1, endpc1, handler_pc1,
1535                              (char)catch_type);
1536            } else {
1537                log.error(pos, "limit.code.too.large.for.try.stmt");
1538                nerrs++;
1539            }
1540        }
1541
1542    public void visitIf(JCIf tree) {
1543        int limit = code.nextreg;
1544        Chain thenExit = null;
1545        Assert.check(code.state.stacksize == 0);
1546        CondItem c = genCond(TreeInfo.skipParens(tree.cond),
1547                             CRT_FLOW_CONTROLLER);
1548        Chain elseChain = c.jumpFalse();
1549        Assert.check(code.state.stacksize == 0);
1550        if (!c.isFalse()) {
1551            code.resolve(c.trueJumps);
1552            genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1553            thenExit = code.branch(goto_);
1554        }
1555        if (elseChain != null) {
1556            code.resolve(elseChain);
1557            if (tree.elsepart != null) {
1558                genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
1559            }
1560        }
1561        code.resolve(thenExit);
1562        code.endScopes(limit);
1563        Assert.check(code.state.stacksize == 0);
1564    }
1565
1566    public void visitExec(JCExpressionStatement tree) {
1567        // Optimize x++ to ++x and x-- to --x.
1568        JCExpression e = tree.expr;
1569        switch (e.getTag()) {
1570            case POSTINC:
1571                ((JCUnary) e).setTag(PREINC);
1572                break;
1573            case POSTDEC:
1574                ((JCUnary) e).setTag(PREDEC);
1575                break;
1576        }
1577        Assert.check(code.state.stacksize == 0);
1578        genExpr(tree.expr, tree.expr.type).drop();
1579        Assert.check(code.state.stacksize == 0);
1580    }
1581
1582    public void visitBreak(JCBreak tree) {
1583        Env<GenContext> targetEnv = unwind(tree.target, env);
1584        Assert.check(code.state.stacksize == 0);
1585        targetEnv.info.addExit(code.branch(goto_));
1586        endFinalizerGaps(env, targetEnv);
1587    }
1588
1589    public void visitContinue(JCContinue tree) {
1590        Env<GenContext> targetEnv = unwind(tree.target, env);
1591        Assert.check(code.state.stacksize == 0);
1592        targetEnv.info.addCont(code.branch(goto_));
1593        endFinalizerGaps(env, targetEnv);
1594    }
1595
1596    public void visitReturn(JCReturn tree) {
1597        int limit = code.nextreg;
1598        final Env<GenContext> targetEnv;
1599
1600        /* Save and then restore the location of the return in case a finally
1601         * is expanded (with unwind()) in the middle of our bytecodes.
1602         */
1603        int tmpPos = code.pendingStatPos;
1604        if (tree.expr != null) {
1605            Assert.check(code.state.stacksize == 0);
1606            Item r = genExpr(tree.expr, pt).load();
1607            if (hasFinally(env.enclMethod, env)) {
1608                r = makeTemp(pt);
1609                r.store();
1610            }
1611            targetEnv = unwind(env.enclMethod, env);
1612            code.pendingStatPos = tmpPos;
1613            r.load();
1614            code.emitop0(ireturn + Code.truncate(Code.typecode(pt)));
1615        } else {
1616            targetEnv = unwind(env.enclMethod, env);
1617            code.pendingStatPos = tmpPos;
1618            code.emitop0(return_);
1619        }
1620        endFinalizerGaps(env, targetEnv);
1621        code.endScopes(limit);
1622    }
1623
1624    public void visitThrow(JCThrow tree) {
1625        Assert.check(code.state.stacksize == 0);
1626        genExpr(tree.expr, tree.expr.type).load();
1627        code.emitop0(athrow);
1628        Assert.check(code.state.stacksize == 0);
1629    }
1630
1631/* ************************************************************************
1632 * Visitor methods for expressions
1633 *************************************************************************/
1634
1635    public void visitApply(JCMethodInvocation tree) {
1636        setTypeAnnotationPositions(tree.pos);
1637        // Generate code for method.
1638        Item m = genExpr(tree.meth, methodType);
1639        // Generate code for all arguments, where the expected types are
1640        // the parameters of the method's external type (that is, any implicit
1641        // outer instance of a super(...) call appears as first parameter).
1642        MethodSymbol msym = (MethodSymbol)TreeInfo.symbol(tree.meth);
1643        genArgs(tree.args,
1644                msym.externalType(types).getParameterTypes());
1645        if (!msym.isDynamic()) {
1646            code.statBegin(tree.pos);
1647        }
1648        result = m.invoke();
1649    }
1650
1651    public void visitConditional(JCConditional tree) {
1652        Chain thenExit = null;
1653        code.statBegin(tree.cond.pos);
1654        CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER);
1655        Chain elseChain = c.jumpFalse();
1656        if (!c.isFalse()) {
1657            code.resolve(c.trueJumps);
1658            int startpc = genCrt ? code.curCP() : 0;
1659            code.statBegin(tree.truepart.pos);
1660            genExpr(tree.truepart, pt).load();
1661            code.state.forceStackTop(tree.type);
1662            if (genCrt) code.crt.put(tree.truepart, CRT_FLOW_TARGET,
1663                                     startpc, code.curCP());
1664            thenExit = code.branch(goto_);
1665        }
1666        if (elseChain != null) {
1667            code.resolve(elseChain);
1668            int startpc = genCrt ? code.curCP() : 0;
1669            code.statBegin(tree.falsepart.pos);
1670            genExpr(tree.falsepart, pt).load();
1671            code.state.forceStackTop(tree.type);
1672            if (genCrt) code.crt.put(tree.falsepart, CRT_FLOW_TARGET,
1673                                     startpc, code.curCP());
1674        }
1675        code.resolve(thenExit);
1676        result = items.makeStackItem(pt);
1677    }
1678
1679    private void setTypeAnnotationPositions(int treePos) {
1680        MethodSymbol meth = code.meth;
1681        boolean initOrClinit = code.meth.getKind() == javax.lang.model.element.ElementKind.CONSTRUCTOR
1682                || code.meth.getKind() == javax.lang.model.element.ElementKind.STATIC_INIT;
1683
1684        for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) {
1685            if (ta.hasUnknownPosition())
1686                ta.tryFixPosition();
1687
1688            if (ta.position.matchesPos(treePos))
1689                ta.position.updatePosOffset(code.cp);
1690        }
1691
1692        if (!initOrClinit)
1693            return;
1694
1695        for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) {
1696            if (ta.hasUnknownPosition())
1697                ta.tryFixPosition();
1698
1699            if (ta.position.matchesPos(treePos))
1700                ta.position.updatePosOffset(code.cp);
1701        }
1702
1703        ClassSymbol clazz = meth.enclClass();
1704        for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
1705            if (!s.getKind().isField())
1706                continue;
1707
1708            for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) {
1709                if (ta.hasUnknownPosition())
1710                    ta.tryFixPosition();
1711
1712                if (ta.position.matchesPos(treePos))
1713                    ta.position.updatePosOffset(code.cp);
1714            }
1715        }
1716    }
1717
1718    public void visitNewClass(JCNewClass tree) {
1719        // Enclosing instances or anonymous classes should have been eliminated
1720        // by now.
1721        Assert.check(tree.encl == null && tree.def == null);
1722        setTypeAnnotationPositions(tree.pos);
1723
1724        code.emitop2(new_, makeRef(tree.pos(), tree.type));
1725        code.emitop0(dup);
1726
1727        // Generate code for all arguments, where the expected types are
1728        // the parameters of the constructor's external type (that is,
1729        // any implicit outer instance appears as first parameter).
1730        genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
1731
1732        items.makeMemberItem(tree.constructor, true).invoke();
1733        result = items.makeStackItem(tree.type);
1734    }
1735
1736    public void visitNewArray(JCNewArray tree) {
1737        setTypeAnnotationPositions(tree.pos);
1738
1739        if (tree.elems != null) {
1740            Type elemtype = types.elemtype(tree.type);
1741            loadIntConst(tree.elems.length());
1742            Item arr = makeNewArray(tree.pos(), tree.type, 1);
1743            int i = 0;
1744            for (List<JCExpression> l = tree.elems; l.nonEmpty(); l = l.tail) {
1745                arr.duplicate();
1746                loadIntConst(i);
1747                i++;
1748                genExpr(l.head, elemtype).load();
1749                items.makeIndexedItem(elemtype).store();
1750            }
1751            result = arr;
1752        } else {
1753            for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
1754                genExpr(l.head, syms.intType).load();
1755            }
1756            result = makeNewArray(tree.pos(), tree.type, tree.dims.length());
1757        }
1758    }
1759//where
1760        /** Generate code to create an array with given element type and number
1761         *  of dimensions.
1762         */
1763        Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
1764            Type elemtype = types.elemtype(type);
1765            if (types.dimensions(type) > ClassFile.MAX_DIMENSIONS) {
1766                log.error(pos, "limit.dimensions");
1767                nerrs++;
1768            }
1769            int elemcode = Code.arraycode(elemtype);
1770            if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
1771                code.emitAnewarray(makeRef(pos, elemtype), type);
1772            } else if (elemcode == 1) {
1773                code.emitMultianewarray(ndims, makeRef(pos, type), type);
1774            } else {
1775                code.emitNewarray(elemcode, type);
1776            }
1777            return items.makeStackItem(type);
1778        }
1779
1780    public void visitParens(JCParens tree) {
1781        result = genExpr(tree.expr, tree.expr.type);
1782    }
1783
1784    public void visitAssign(JCAssign tree) {
1785        Item l = genExpr(tree.lhs, tree.lhs.type);
1786        genExpr(tree.rhs, tree.lhs.type).load();
1787        if (tree.rhs.type.hasTag(BOT)) {
1788            /* This is just a case of widening reference conversion that per 5.1.5 simply calls
1789               for "regarding a reference as having some other type in a manner that can be proved
1790               correct at compile time."
1791            */
1792            code.state.forceStackTop(tree.lhs.type);
1793        }
1794        result = items.makeAssignItem(l);
1795    }
1796
1797    public void visitAssignop(JCAssignOp tree) {
1798        OperatorSymbol operator = (OperatorSymbol) tree.operator;
1799        Item l;
1800        if (operator.opcode == string_add) {
1801            l = concat.makeConcat(tree);
1802        } else {
1803            // Generate code for first expression
1804            l = genExpr(tree.lhs, tree.lhs.type);
1805
1806            // If we have an increment of -32768 to +32767 of a local
1807            // int variable we can use an incr instruction instead of
1808            // proceeding further.
1809            if ((tree.hasTag(PLUS_ASG) || tree.hasTag(MINUS_ASG)) &&
1810                l instanceof LocalItem &&
1811                tree.lhs.type.getTag().isSubRangeOf(INT) &&
1812                tree.rhs.type.getTag().isSubRangeOf(INT) &&
1813                tree.rhs.type.constValue() != null) {
1814                int ival = ((Number) tree.rhs.type.constValue()).intValue();
1815                if (tree.hasTag(MINUS_ASG)) ival = -ival;
1816                ((LocalItem)l).incr(ival);
1817                result = l;
1818                return;
1819            }
1820            // Otherwise, duplicate expression, load one copy
1821            // and complete binary operation.
1822            l.duplicate();
1823            l.coerce(operator.type.getParameterTypes().head).load();
1824            completeBinop(tree.lhs, tree.rhs, operator).coerce(tree.lhs.type);
1825        }
1826        result = items.makeAssignItem(l);
1827    }
1828
1829    public void visitUnary(JCUnary tree) {
1830        OperatorSymbol operator = (OperatorSymbol)tree.operator;
1831        if (tree.hasTag(NOT)) {
1832            CondItem od = genCond(tree.arg, false);
1833            result = od.negate();
1834        } else {
1835            Item od = genExpr(tree.arg, operator.type.getParameterTypes().head);
1836            switch (tree.getTag()) {
1837            case POS:
1838                result = od.load();
1839                break;
1840            case NEG:
1841                result = od.load();
1842                code.emitop0(operator.opcode);
1843                break;
1844            case COMPL:
1845                result = od.load();
1846                emitMinusOne(od.typecode);
1847                code.emitop0(operator.opcode);
1848                break;
1849            case PREINC: case PREDEC:
1850                od.duplicate();
1851                if (od instanceof LocalItem &&
1852                    (operator.opcode == iadd || operator.opcode == isub)) {
1853                    ((LocalItem)od).incr(tree.hasTag(PREINC) ? 1 : -1);
1854                    result = od;
1855                } else {
1856                    od.load();
1857                    code.emitop0(one(od.typecode));
1858                    code.emitop0(operator.opcode);
1859                    // Perform narrowing primitive conversion if byte,
1860                    // char, or short.  Fix for 4304655.
1861                    if (od.typecode != INTcode &&
1862                        Code.truncate(od.typecode) == INTcode)
1863                      code.emitop0(int2byte + od.typecode - BYTEcode);
1864                    result = items.makeAssignItem(od);
1865                }
1866                break;
1867            case POSTINC: case POSTDEC:
1868                od.duplicate();
1869                if (od instanceof LocalItem &&
1870                    (operator.opcode == iadd || operator.opcode == isub)) {
1871                    Item res = od.load();
1872                    ((LocalItem)od).incr(tree.hasTag(POSTINC) ? 1 : -1);
1873                    result = res;
1874                } else {
1875                    Item res = od.load();
1876                    od.stash(od.typecode);
1877                    code.emitop0(one(od.typecode));
1878                    code.emitop0(operator.opcode);
1879                    // Perform narrowing primitive conversion if byte,
1880                    // char, or short.  Fix for 4304655.
1881                    if (od.typecode != INTcode &&
1882                        Code.truncate(od.typecode) == INTcode)
1883                      code.emitop0(int2byte + od.typecode - BYTEcode);
1884                    od.store();
1885                    result = res;
1886                }
1887                break;
1888            case NULLCHK:
1889                result = od.load();
1890                code.emitop0(dup);
1891                genNullCheck(tree.pos());
1892                break;
1893            default:
1894                Assert.error();
1895            }
1896        }
1897    }
1898
1899    /** Generate a null check from the object value at stack top. */
1900    private void genNullCheck(DiagnosticPosition pos) {
1901        if (allowBetterNullChecks) {
1902            callMethod(pos, syms.objectsType, names.requireNonNull,
1903                    List.of(syms.objectType), true);
1904        } else {
1905            callMethod(pos, syms.objectType, names.getClass,
1906                    List.<Type>nil(), false);
1907        }
1908        code.emitop0(pop);
1909    }
1910
1911    public void visitBinary(JCBinary tree) {
1912        OperatorSymbol operator = (OperatorSymbol)tree.operator;
1913        if (operator.opcode == string_add) {
1914            result = concat.makeConcat(tree);
1915        } else if (tree.hasTag(AND)) {
1916            CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1917            if (!lcond.isFalse()) {
1918                Chain falseJumps = lcond.jumpFalse();
1919                code.resolve(lcond.trueJumps);
1920                CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1921                result = items.
1922                    makeCondItem(rcond.opcode,
1923                                 rcond.trueJumps,
1924                                 Code.mergeChains(falseJumps,
1925                                                  rcond.falseJumps));
1926            } else {
1927                result = lcond;
1928            }
1929        } else if (tree.hasTag(OR)) {
1930            CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1931            if (!lcond.isTrue()) {
1932                Chain trueJumps = lcond.jumpTrue();
1933                code.resolve(lcond.falseJumps);
1934                CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1935                result = items.
1936                    makeCondItem(rcond.opcode,
1937                                 Code.mergeChains(trueJumps, rcond.trueJumps),
1938                                 rcond.falseJumps);
1939            } else {
1940                result = lcond;
1941            }
1942        } else {
1943            Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
1944            od.load();
1945            result = completeBinop(tree.lhs, tree.rhs, operator);
1946        }
1947    }
1948
1949
1950        /** Complete generating code for operation, with left operand
1951         *  already on stack.
1952         *  @param lhs       The tree representing the left operand.
1953         *  @param rhs       The tree representing the right operand.
1954         *  @param operator  The operator symbol.
1955         */
1956        Item completeBinop(JCTree lhs, JCTree rhs, OperatorSymbol operator) {
1957            MethodType optype = (MethodType)operator.type;
1958            int opcode = operator.opcode;
1959            if (opcode >= if_icmpeq && opcode <= if_icmple &&
1960                rhs.type.constValue() instanceof Number &&
1961                ((Number) rhs.type.constValue()).intValue() == 0) {
1962                opcode = opcode + (ifeq - if_icmpeq);
1963            } else if (opcode >= if_acmpeq && opcode <= if_acmpne &&
1964                       TreeInfo.isNull(rhs)) {
1965                opcode = opcode + (if_acmp_null - if_acmpeq);
1966            } else {
1967                // The expected type of the right operand is
1968                // the second parameter type of the operator, except for
1969                // shifts with long shiftcount, where we convert the opcode
1970                // to a short shift and the expected type to int.
1971                Type rtype = operator.erasure(types).getParameterTypes().tail.head;
1972                if (opcode >= ishll && opcode <= lushrl) {
1973                    opcode = opcode + (ishl - ishll);
1974                    rtype = syms.intType;
1975                }
1976                // Generate code for right operand and load.
1977                genExpr(rhs, rtype).load();
1978                // If there are two consecutive opcode instructions,
1979                // emit the first now.
1980                if (opcode >= (1 << preShift)) {
1981                    code.emitop0(opcode >> preShift);
1982                    opcode = opcode & 0xFF;
1983                }
1984            }
1985            if (opcode >= ifeq && opcode <= if_acmpne ||
1986                opcode == if_acmp_null || opcode == if_acmp_nonnull) {
1987                return items.makeCondItem(opcode);
1988            } else {
1989                code.emitop0(opcode);
1990                return items.makeStackItem(optype.restype);
1991            }
1992        }
1993
1994    public void visitTypeCast(JCTypeCast tree) {
1995        result = genExpr(tree.expr, tree.clazz.type).load();
1996        setTypeAnnotationPositions(tree.pos);
1997        // Additional code is only needed if we cast to a reference type
1998        // which is not statically a supertype of the expression's type.
1999        // For basic types, the coerce(...) in genExpr(...) will do
2000        // the conversion.
2001        if (!tree.clazz.type.isPrimitive() &&
2002           !types.isSameType(tree.expr.type, tree.clazz.type) &&
2003           types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
2004            code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
2005        }
2006    }
2007
2008    public void visitWildcard(JCWildcard tree) {
2009        throw new AssertionError(this.getClass().getName());
2010    }
2011
2012    public void visitTypeTest(JCInstanceOf tree) {
2013        genExpr(tree.expr, tree.expr.type).load();
2014        setTypeAnnotationPositions(tree.pos);
2015        code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type));
2016        result = items.makeStackItem(syms.booleanType);
2017    }
2018
2019    public void visitIndexed(JCArrayAccess tree) {
2020        genExpr(tree.indexed, tree.indexed.type).load();
2021        genExpr(tree.index, syms.intType).load();
2022        result = items.makeIndexedItem(tree.type);
2023    }
2024
2025    public void visitIdent(JCIdent tree) {
2026        Symbol sym = tree.sym;
2027        if (tree.name == names._this || tree.name == names._super) {
2028            Item res = tree.name == names._this
2029                ? items.makeThisItem()
2030                : items.makeSuperItem();
2031            if (sym.kind == MTH) {
2032                // Generate code to address the constructor.
2033                res.load();
2034                res = items.makeMemberItem(sym, true);
2035            }
2036            result = res;
2037        } else if (sym.kind == VAR && sym.owner.kind == MTH) {
2038            result = items.makeLocalItem((VarSymbol)sym);
2039        } else if (isInvokeDynamic(sym)) {
2040            result = items.makeDynamicItem(sym);
2041        } else if ((sym.flags() & STATIC) != 0) {
2042            if (!isAccessSuper(env.enclMethod))
2043                sym = binaryQualifier(sym, env.enclClass.type);
2044            result = items.makeStaticItem(sym);
2045        } else {
2046            items.makeThisItem().load();
2047            sym = binaryQualifier(sym, env.enclClass.type);
2048            result = items.makeMemberItem(sym, (sym.flags() & PRIVATE) != 0);
2049        }
2050    }
2051
2052    public void visitSelect(JCFieldAccess tree) {
2053        Symbol sym = tree.sym;
2054
2055        if (tree.name == names._class) {
2056            code.emitLdc(makeRef(tree.pos(), tree.selected.type));
2057            result = items.makeStackItem(pt);
2058            return;
2059       }
2060
2061        Symbol ssym = TreeInfo.symbol(tree.selected);
2062
2063        // Are we selecting via super?
2064        boolean selectSuper =
2065            ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2066
2067        // Are we accessing a member of the superclass in an access method
2068        // resulting from a qualified super?
2069        boolean accessSuper = isAccessSuper(env.enclMethod);
2070
2071        Item base = (selectSuper)
2072            ? items.makeSuperItem()
2073            : genExpr(tree.selected, tree.selected.type);
2074
2075        if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2076            // We are seeing a variable that is constant but its selecting
2077            // expression is not.
2078            if ((sym.flags() & STATIC) != 0) {
2079                if (!selectSuper && (ssym == null || ssym.kind != TYP))
2080                    base = base.load();
2081                base.drop();
2082            } else {
2083                base.load();
2084                genNullCheck(tree.selected.pos());
2085            }
2086            result = items.
2087                makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
2088        } else {
2089            if (isInvokeDynamic(sym)) {
2090                result = items.makeDynamicItem(sym);
2091                return;
2092            } else {
2093                sym = binaryQualifier(sym, tree.selected.type);
2094            }
2095            if ((sym.flags() & STATIC) != 0) {
2096                if (!selectSuper && (ssym == null || ssym.kind != TYP))
2097                    base = base.load();
2098                base.drop();
2099                result = items.makeStaticItem(sym);
2100            } else {
2101                base.load();
2102                if (sym == syms.lengthVar) {
2103                    code.emitop0(arraylength);
2104                    result = items.makeStackItem(syms.intType);
2105                } else {
2106                    result = items.
2107                        makeMemberItem(sym,
2108                                       (sym.flags() & PRIVATE) != 0 ||
2109                                       selectSuper || accessSuper);
2110                }
2111            }
2112        }
2113    }
2114
2115    public boolean isInvokeDynamic(Symbol sym) {
2116        return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
2117    }
2118
2119    public void visitLiteral(JCLiteral tree) {
2120        if (tree.type.hasTag(BOT)) {
2121            code.emitop0(aconst_null);
2122            result = items.makeStackItem(tree.type);
2123        }
2124        else
2125            result = items.makeImmediateItem(tree.type, tree.value);
2126    }
2127
2128    public void visitLetExpr(LetExpr tree) {
2129        letExprDepth++;
2130        int limit = code.nextreg;
2131        genStats(tree.defs, env);
2132        result = genExpr(tree.expr, tree.expr.type).load();
2133        code.endScopes(limit);
2134        letExprDepth--;
2135    }
2136
2137    private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
2138        List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
2139        if (prunedInfo != null) {
2140            for (JCTree prunedTree: prunedInfo) {
2141                prunedTree.accept(classReferenceVisitor);
2142            }
2143        }
2144    }
2145
2146/* ************************************************************************
2147 * main method
2148 *************************************************************************/
2149
2150    /** Generate code for a class definition.
2151     *  @param env   The attribution environment that belongs to the
2152     *               outermost class containing this class definition.
2153     *               We need this for resolving some additional symbols.
2154     *  @param cdef  The tree representing the class definition.
2155     *  @return      True if code is generated with no errors.
2156     */
2157    public boolean genClass(Env<AttrContext> env, JCClassDecl cdef) {
2158        try {
2159            attrEnv = env;
2160            ClassSymbol c = cdef.sym;
2161            this.toplevel = env.toplevel;
2162            this.endPosTable = toplevel.endPositions;
2163            c.pool = pool;
2164            pool.reset();
2165            /* method normalizeDefs() can add references to external classes into the constant pool
2166             */
2167            cdef.defs = normalizeDefs(cdef.defs, c);
2168            generateReferencesToPrunedTree(c, pool);
2169            Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
2170            localEnv.toplevel = env.toplevel;
2171            localEnv.enclClass = cdef;
2172
2173            for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2174                genDef(l.head, localEnv);
2175            }
2176            if (pool.numEntries() > Pool.MAX_ENTRIES) {
2177                log.error(cdef.pos(), "limit.pool");
2178                nerrs++;
2179            }
2180            if (nerrs != 0) {
2181                // if errors, discard code
2182                for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2183                    if (l.head.hasTag(METHODDEF))
2184                        ((JCMethodDecl) l.head).sym.code = null;
2185                }
2186            }
2187            cdef.defs = List.nil(); // discard trees
2188            return nerrs == 0;
2189        } finally {
2190            // note: this method does NOT support recursion.
2191            attrEnv = null;
2192            this.env = null;
2193            toplevel = null;
2194            endPosTable = null;
2195            nerrs = 0;
2196        }
2197    }
2198
2199/* ************************************************************************
2200 * Auxiliary classes
2201 *************************************************************************/
2202
2203    /** An abstract class for finalizer generation.
2204     */
2205    abstract class GenFinalizer {
2206        /** Generate code to clean up when unwinding. */
2207        abstract void gen();
2208
2209        /** Generate code to clean up at last. */
2210        abstract void genLast();
2211
2212        /** Does this finalizer have some nontrivial cleanup to perform? */
2213        boolean hasFinalizer() { return true; }
2214    }
2215
2216    /** code generation contexts,
2217     *  to be used as type parameter for environments.
2218     */
2219    static class GenContext {
2220
2221        /** A chain for all unresolved jumps that exit the current environment.
2222         */
2223        Chain exit = null;
2224
2225        /** A chain for all unresolved jumps that continue in the
2226         *  current environment.
2227         */
2228        Chain cont = null;
2229
2230        /** A closure that generates the finalizer of the current environment.
2231         *  Only set for Synchronized and Try contexts.
2232         */
2233        GenFinalizer finalize = null;
2234
2235        /** Is this a switch statement?  If so, allocate registers
2236         * even when the variable declaration is unreachable.
2237         */
2238        boolean isSwitch = false;
2239
2240        /** A list buffer containing all gaps in the finalizer range,
2241         *  where a catch all exception should not apply.
2242         */
2243        ListBuffer<Integer> gaps = null;
2244
2245        /** Add given chain to exit chain.
2246         */
2247        void addExit(Chain c)  {
2248            exit = Code.mergeChains(c, exit);
2249        }
2250
2251        /** Add given chain to cont chain.
2252         */
2253        void addCont(Chain c) {
2254            cont = Code.mergeChains(c, cont);
2255        }
2256    }
2257
2258}
2259