EMMA Coverage Report (generated Thu Dec 06 15:52:10 GMT 2007)
[all classes][com.sun.tools.javac.jvm]

COVERAGE SUMMARY FOR SOURCE FILE [Gen.java]

nameclass, %method, %block, %line, %
Gen.java29%  (2/7)25%  (34/137)21%  (1244/6054)22%  (231.7/1061)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Gen$10%   (0/1)0%   (0/4)0%   (0/74)0%   (0/10)
<static initializer> 0%   (0/1)0%   (0/8)0%   (0/1)
Gen$1 (Gen, Env, Items$LocalItem): void 0%   (0/1)0%   (0/13)0%   (0/1)
gen (): void 0%   (0/1)0%   (0/30)0%   (0/4)
genLast (): void 0%   (0/1)0%   (0/23)0%   (0/5)
     
class Gen$1ComplexityScanner0%   (0/1)0%   (0/32)0%   (0/335)0%   (0/43)
Gen$1ComplexityScanner (Gen): void 0%   (0/1)0%   (0/9)0%   (0/2)
scan (JCTree): void 0%   (0/1)0%   (0/11)0%   (0/3)
visitApply (JCTree$JCMethodInvocation): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitAssert (JCTree$JCAssert): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitAssign (JCTree$JCAssign): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitAssignop (JCTree$JCAssignOp): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitBinary (JCTree$JCBinary): void 0%   (0/1)0%   (0/14)0%   (0/2)
visitBreak (JCTree$JCBreak): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitCase (JCTree$JCCase): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitCatch (JCTree$JCCatch): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitClassDef (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitConditional (JCTree$JCConditional): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitContinue (JCTree$JCContinue): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitDoLoop (JCTree$JCDoWhileLoop): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitForLoop (JCTree$JCForLoop): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitIdent (JCTree$JCIdent): void 0%   (0/1)0%   (0/28)0%   (0/5)
visitIf (JCTree$JCIf): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitIndexed (JCTree$JCArrayAccess): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitLiteral (JCTree$JCLiteral): void 0%   (0/1)0%   (0/7)0%   (0/1)
visitNewArray (JCTree$JCNewArray): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitNewClass (JCTree$JCNewClass): void 0%   (0/1)0%   (0/15)0%   (0/1)
visitReturn (JCTree$JCReturn): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitSelect (JCTree$JCFieldAccess): void 0%   (0/1)0%   (0/15)0%   (0/2)
visitSwitch (JCTree$JCSwitch): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitSynchronized (JCTree$JCSynchronized): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitThrow (JCTree$JCThrow): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitTree (JCTree): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitTry (JCTree$JCTry): void 0%   (0/1)0%   (0/13)0%   (0/2)
visitTypeTest (JCTree$JCInstanceOf): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitUnary (JCTree$JCUnary): void 0%   (0/1)0%   (0/14)0%   (0/2)
visitWhileLoop (JCTree$JCWhileLoop): void 0%   (0/1)0%   (0/10)0%   (0/1)
visitWildcard (JCTree$JCWildcard): void 0%   (0/1)0%   (0/7)0%   (0/1)
     
class Gen$20%   (0/1)0%   (0/5)0%   (0/144)0%   (0/16)
<static initializer> 0%   (0/1)0%   (0/8)0%   (0/1)
Gen$2 (Gen, JCTree$JCTry, Env, Env): void 0%   (0/1)0%   (0/16)0%   (0/1)
gen (): void 0%   (0/1)0%   (0/98)0%   (0/11)
genLast (): void 0%   (0/1)0%   (0/14)0%   (0/3)
hasFinalizer (): boolean 0%   (0/1)0%   (0/8)0%   (0/1)
     
class Gen$CodeSizeOverflow0%   (0/1)0%   (0/1)0%   (0/3)0%   (0/1)
Gen$CodeSizeOverflow (): void 0%   (0/1)0%   (0/3)0%   (0/1)
     
class Gen$GenFinalizer0%   (0/1)0%   (0/2)0%   (0/8)0%   (0/2)
Gen$GenFinalizer (Gen): void 0%   (0/1)0%   (0/6)0%   (0/1)
hasFinalizer (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
     
class Gen100% (1/1)37%  (33/90)22%  (1226/5458)23%  (225.7/981)
access$000 (Gen): Code 0%   (0/1)0%   (0/3)0%   (0/1)
access$100 (Gen): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
access$200 (Gen): int 0%   (0/1)0%   (0/3)0%   (0/1)
addAbstractMethod (Symbol$ClassSymbol, Symbol$MethodSymbol): void 0%   (0/1)0%   (0/20)0%   (0/3)
adjustAbstractMethod (Symbol$ClassSymbol, Symbol$MethodSymbol, Symbol$MethodS... 0%   (0/1)0%   (0/21)0%   (0/4)
appendString (JCTree): void 0%   (0/1)0%   (0/30)0%   (0/5)
appendStrings (JCTree): void 0%   (0/1)0%   (0/45)0%   (0/10)
bufferToString (JCDiagnostic$DiagnosticPosition): void 0%   (0/1)0%   (0/11)0%   (0/2)
callMethod (JCDiagnostic$DiagnosticPosition, Type, Name, List, boolean): void 0%   (0/1)0%   (0/35)0%   (0/4)
checkStringConstant (JCDiagnostic$DiagnosticPosition, Object): void 0%   (0/1)0%   (0/28)0%   (0/5)
completeBinop (JCTree, JCTree, Symbol$OperatorSymbol): Items$Item 0%   (0/1)0%   (0/112)0%   (0/18)
emitMinusOne (int): void 0%   (0/1)0%   (0/21)0%   (0/4)
estimateCodeComplexity (JCTree): int 0%   (0/1)0%   (0/15)0%   (0/4)
genCatch (JCTree$JCCatch, Env, int, int, List): void 0%   (0/1)0%   (0/103)0%   (0/22)
genCond (JCTree, boolean): Items$CondItem 0%   (0/1)0%   (0/146)0%   (0/29)
genCond (JCTree, int): Items$CondItem 0%   (0/1)0%   (0/35)0%   (0/5)
genLoop (JCTree$JCStatement, JCTree$JCStatement, JCTree$JCExpression, List, b... 0%   (0/1)0%   (0/124)0%   (0/26)
genNullCheck (JCDiagnostic$DiagnosticPosition): void 0%   (0/1)0%   (0/16)0%   (0/3)
genStats (List, Env, int): void 0%   (0/1)0%   (0/41)0%   (0/9)
genTry (JCTree, List, Env): void 0%   (0/1)0%   (0/267)0%   (0/50)
getStringBufferAppend (JCTree, Type): Symbol 0%   (0/1)0%   (0/41)0%   (0/6)
implementInterfaceMethods (Symbol$ClassSymbol): void 0%   (0/1)0%   (0/5)0%   (0/2)
implementInterfaceMethods (Symbol$ClassSymbol, Symbol$ClassSymbol): void 0%   (0/1)0%   (0/76)0%   (0/14)
isOddAccessName (Name): boolean 0%   (0/1)0%   (0/19)0%   (0/1)
loadIntConst (int): void 0%   (0/1)0%   (0/11)0%   (0/2)
makeNewArray (JCDiagnostic$DiagnosticPosition, Type, int): Items$Item 0%   (0/1)0%   (0/69)0%   (0/11)
makeStringBuffer (JCDiagnostic$DiagnosticPosition): void 0%   (0/1)0%   (0/24)0%   (0/4)
makeTemp (Type): Items$LocalItem 0%   (0/1)0%   (0/23)0%   (0/3)
normalizeMethod (JCTree$JCMethodDecl, List): void 0%   (0/1)0%   (0/95)0%   (0/20)
one (int): int 0%   (0/1)0%   (0/5)0%   (0/1)
qsort2 (int [], int [], int, int): void 0%   (0/1)0%   (0/79)0%   (0/18)
registerCatch (JCDiagnostic$DiagnosticPosition, int, int, int, int): void 0%   (0/1)0%   (0/58)0%   (0/12)
visitAssignop (JCTree$JCAssignOp): void 0%   (0/1)0%   (0/138)0%   (0/22)
visitBinary (JCTree$JCBinary): void 0%   (0/1)0%   (0/147)0%   (0/29)
visitBreak (JCTree$JCBreak): void 0%   (0/1)0%   (0/32)0%   (0/5)
visitConditional (JCTree$JCConditional): void 0%   (0/1)0%   (0/116)0%   (0/19)
visitContinue (JCTree$JCContinue): void 0%   (0/1)0%   (0/32)0%   (0/5)
visitDoLoop (JCTree$JCDoWhileLoop): void 0%   (0/1)0%   (0/10)0%   (0/2)
visitForLoop (JCTree$JCForLoop): void 0%   (0/1)0%   (0/25)0%   (0/5)
visitForeachLoop (JCTree$JCEnhancedForLoop): void 0%   (0/1)0%   (0/4)0%   (0/1)
visitIf (JCTree$JCIf): void 0%   (0/1)0%   (0/61)0%   (0/15)
visitIndexed (JCTree$JCArrayAccess): void 0%   (0/1)0%   (0/26)0%   (0/4)
visitLabelled (JCTree$JCLabeledStatement): void 0%   (0/1)0%   (0/22)0%   (0/4)
visitLetExpr (JCTree$LetExpr): void 0%   (0/1)0%   (0/25)0%   (0/5)
visitLiteral (JCTree$JCLiteral): void 0%   (0/1)0%   (0/52)0%   (0/8)
visitNewArray (JCTree$JCNewArray): void 0%   (0/1)0%   (0/89)0%   (0/17)
visitSkip (JCTree$JCSkip): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitSwitch (JCTree$JCSwitch): void 0%   (0/1)0%   (0/485)0%   (0/86)
visitSynchronized (JCTree$JCSynchronized): void 0%   (0/1)0%   (0/67)0%   (0/12)
visitThrow (JCTree$JCThrow): void 0%   (0/1)0%   (0/14)0%   (0/3)
visitTry (JCTree$JCTry): void 0%   (0/1)0%   (0/63)0%   (0/8)
visitTypeTest (JCTree$JCInstanceOf): void 0%   (0/1)0%   (0/29)0%   (0/4)
visitUnary (JCTree$JCUnary): void 0%   (0/1)0%   (0/215)0%   (0/48)
visitVarDef (JCTree$JCVariableDecl): void 0%   (0/1)0%   (0/46)0%   (0/9)
visitWhileLoop (JCTree$JCWhileLoop): void 0%   (0/1)0%   (0/10)0%   (0/2)
visitWildcard (JCTree$JCWildcard): void 0%   (0/1)0%   (0/7)0%   (0/1)
zero (int): int 0%   (0/1)0%   (0/15)0%   (0/6)
binaryQualifier (Symbol, Type): Symbol 100% (1/1)8%   (11/132)13%  (2.4/18)
genStat (JCTree, Env, int): void 100% (1/1)23%  (8/35)38%  (3/8)
endFinalizerGap (Env): void 100% (1/1)24%  (6/25)45%  (1.4/3)
normalizeDefs (List, Symbol$ClassSymbol): List 100% (1/1)24%  (57/236)34%  (15/44)
genExpr (JCTree, Type): Items$Item 100% (1/1)33%  (23/70)44%  (5.2/12)
genDef (JCTree, Env): void 100% (1/1)44%  (14/32)62%  (4.9/8)
visitSelect (JCTree$JCFieldAccess): void 100% (1/1)46%  (94/204)44%  (13.7/31)
genStat (JCTree, Env): void 100% (1/1)48%  (15/31)67%  (4/6)
genMethod (JCTree$JCMethodDecl, Env, boolean): void 100% (1/1)51%  (97/191)51%  (16.4/32)
visitIdent (JCTree$JCIdent): void 100% (1/1)53%  (64/121)59%  (10/17)
checkDimension (JCDiagnostic$DiagnosticPosition, Type): void 100% (1/1)57%  (26/46)67%  (6/9)
genClass (Env, JCTree$JCClassDecl): boolean 100% (1/1)59%  (97/165)68%  (19.1/28)
isAccessSuper (JCTree$JCMethodDecl): boolean 100% (1/1)59%  (10/17)58%  (0.6/1)
visitExec (JCTree$JCExpressionStatement): void 100% (1/1)62%  (15/24)57%  (4/7)
visitBlock (JCTree$JCBlock): void 100% (1/1)65%  (24/37)62%  (5/8)
hasFinally (JCTree, Env): boolean 100% (1/1)65%  (15/23)69%  (3.4/5)
genFinalizer (Env): void 100% (1/1)67%  (10/15)67%  (2/3)
visitReturn (JCTree$JCReturn): void 100% (1/1)74%  (54/73)73%  (11/15)
genArgs (List, List): void 100% (1/1)78%  (25/32)84%  (4.2/5)
visitNewClass (JCTree$JCNewClass): void 100% (1/1)81%  (42/52)88%  (6.2/7)
Gen (Context): void 100% (1/1)82%  (166/202)84%  (31.1/37)
initCode (JCTree$JCMethodDecl, Env, boolean): int 100% (1/1)85%  (138/163)92%  (15.6/17)
<static initializer> 100% (1/1)92%  (11/12)96%  (1.9/2)
makeRef (JCDiagnostic$DiagnosticPosition, Type): int 100% (1/1)94%  (15/16)96%  (1.9/2)
endFinalizerGaps (Env, Env): void 100% (1/1)100% (15/15)100% (6/6)
genStats (List, Env): void 100% (1/1)100% (17/17)100% (3/3)
instance (Context): Gen 100% (1/1)100% (14/14)100% (4/4)
unwind (JCTree, Env): Env 100% (1/1)100% (16/16)100% (5/5)
visitApply (JCTree$JCMethodInvocation): void 100% (1/1)100% (23/23)100% (4/4)
visitAssign (JCTree$JCAssign): void 100% (1/1)100% (24/24)100% (4/4)
visitMethodDef (JCTree$JCMethodDecl): void 100% (1/1)100% (31/31)100% (6/6)
visitParens (JCTree$JCParens): void 100% (1/1)100% (10/10)100% (2/2)
visitTypeCast (JCTree$JCTypeCast): void 100% (1/1)100% (39/39)100% (4/4)
     
class Gen$GenContext100% (1/1)33%  (1/3)56%  (18/32)60%  (6/10)
addCont (Code$Chain): void 0%   (0/1)0%   (0/7)0%   (0/2)
addExit (Code$Chain): void 0%   (0/1)0%   (0/7)0%   (0/2)
Gen$GenContext (): void 100% (1/1)100% (18/18)100% (6/6)

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

[all classes][com.sun.tools.javac.jvm]
EMMA 2.0.5312 (C) Vladimir Roubtsov