Source Code Cross Referenced for Gen.java in  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » javac » jvm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules com.sun » tools » com.sun.tools.javac.jvm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.tools.javac.jvm;
0027:
0028:        import java.util.*;
0029:
0030:        import com.sun.tools.javac.util.*;
0031:        import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
0032:        import com.sun.tools.javac.util.List;
0033:        import com.sun.tools.javac.code.*;
0034:        import com.sun.tools.javac.comp.*;
0035:        import com.sun.tools.javac.tree.*;
0036:
0037:        import com.sun.tools.javac.code.Symbol.*;
0038:        import com.sun.tools.javac.code.Type.*;
0039:        import com.sun.tools.javac.jvm.Code.*;
0040:        import com.sun.tools.javac.jvm.Items.*;
0041:        import com.sun.tools.javac.tree.JCTree.*;
0042:
0043:        import static com.sun.tools.javac.code.Flags.*;
0044:        import static com.sun.tools.javac.code.Kinds.*;
0045:        import static com.sun.tools.javac.code.TypeTags.*;
0046:        import static com.sun.tools.javac.jvm.ByteCodes.*;
0047:        import static com.sun.tools.javac.jvm.CRTFlags.*;
0048:
0049:        /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
0050:         *
0051:         *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
0052:         *  you write code that depends on this, you do so at your own risk.
0053:         *  This code and its internal interfaces are subject to change or
0054:         *  deletion without notice.</b>
0055:         */
0056:        @Version("@(#)Gen.java	1.154 07/06/14")
0057:        public class Gen extends JCTree.Visitor {
0058:            protected static final Context.Key<Gen> genKey = new Context.Key<Gen>();
0059:
0060:            private final Log log;
0061:            private final Symtab syms;
0062:            private final Check chk;
0063:            private final Resolve rs;
0064:            private final TreeMaker make;
0065:            private final Name.Table names;
0066:            private final Target target;
0067:            private final Type stringBufferType;
0068:            private final Map<Type, Symbol> stringBufferAppend;
0069:            private Name accessDollar;
0070:            private final Types types;
0071:
0072:            /** Switch: GJ mode?
0073:             */
0074:            private final boolean allowGenerics;
0075:
0076:            /** Set when Miranda method stubs are to be generated. */
0077:            private final boolean generateIproxies;
0078:
0079:            /** Format of stackmap tables to be generated. */
0080:            private final Code.StackMapFormat stackMap;
0081:
0082:            /** A type that serves as the expected type for all method expressions.
0083:             */
0084:            private final Type methodType;
0085:
0086:            public static Gen instance(Context context) {
0087:                Gen instance = context.get(genKey);
0088:                if (instance == null)
0089:                    instance = new Gen(context);
0090:                return instance;
0091:            }
0092:
0093:            protected Gen(Context context) {
0094:                context.put(genKey, this );
0095:
0096:                names = Name.Table.instance(context);
0097:                log = Log.instance(context);
0098:                syms = Symtab.instance(context);
0099:                chk = Check.instance(context);
0100:                rs = Resolve.instance(context);
0101:                make = TreeMaker.instance(context);
0102:                target = Target.instance(context);
0103:                types = Types.instance(context);
0104:                methodType = new MethodType(null, null, null, syms.methodClass);
0105:                allowGenerics = Source.instance(context).allowGenerics();
0106:                stringBufferType = target.useStringBuilder() ? syms.stringBuilderType
0107:                        : syms.stringBufferType;
0108:                stringBufferAppend = new HashMap<Type, Symbol>();
0109:                accessDollar = names.fromString("access"
0110:                        + target.syntheticNameChar());
0111:
0112:                Options options = Options.instance(context);
0113:                lineDebugInfo = options.get("-g:") == null
0114:                        || options.get("-g:lines") != null;
0115:                varDebugInfo = options.get("-g:") == null ? options.get("-g") != null
0116:                        : options.get("-g:vars") != null;
0117:                genCrt = options.get("-Xjcov") != null;
0118:                debugCode = options.get("debugcode") != null;
0119:
0120:                generateIproxies = target.requiresIproxy()
0121:                        || options.get("miranda") != null;
0122:
0123:                if (target.generateStackMapTable()) {
0124:                    // ignore cldc because we cannot have both stackmap formats
0125:                    this .stackMap = StackMapFormat.JSR202;
0126:                } else {
0127:                    if (target.generateCLDCStackmap()) {
0128:                        this .stackMap = StackMapFormat.CLDC;
0129:                    } else {
0130:                        this .stackMap = StackMapFormat.NONE;
0131:                    }
0132:                }
0133:
0134:                // by default, avoid jsr's for simple finalizers
0135:                int setjsrlimit = 50;
0136:                String jsrlimitString = options.get("jsrlimit");
0137:                if (jsrlimitString != null) {
0138:                    try {
0139:                        setjsrlimit = Integer.parseInt(jsrlimitString);
0140:                    } catch (NumberFormatException ex) {
0141:                        // ignore ill-formed numbers for jsrlimit
0142:                    }
0143:                }
0144:                this .jsrlimit = setjsrlimit;
0145:                this .useJsrLocally = false; // reset in visitTry
0146:            }
0147:
0148:            /** Switches
0149:             */
0150:            private final boolean lineDebugInfo;
0151:            private final boolean varDebugInfo;
0152:            private final boolean genCrt;
0153:            private final boolean debugCode;
0154:
0155:            /** Default limit of (approximate) size of finalizer to inline.
0156:             *  Zero means always use jsr.  100 or greater means never use
0157:             *  jsr.
0158:             */
0159:            private final int jsrlimit;
0160:
0161:            /** True if jsr is used.
0162:             */
0163:            private boolean useJsrLocally;
0164:
0165:            /* Constant pool, reset by genClass.
0166:             */
0167:            private Pool pool = new Pool();
0168:
0169:            /** Code buffer, set by genMethod.
0170:             */
0171:            private Code code;
0172:
0173:            /** Items structure, set by genMethod.
0174:             */
0175:            private Items items;
0176:
0177:            /** Environment for symbol lookup, set by genClass
0178:             */
0179:            private Env<AttrContext> attrEnv;
0180:
0181:            /** The top level tree.
0182:             */
0183:            private JCCompilationUnit toplevel;
0184:
0185:            /** The number of code-gen errors in this class.
0186:             */
0187:            private int nerrs = 0;
0188:
0189:            /** A hash table mapping syntax trees to their ending source positions.
0190:             */
0191:            private Map<JCTree, Integer> endPositions;
0192:
0193:            /** Generate code to load an integer constant.
0194:             *  @param n     The integer to be loaded.
0195:             */
0196:            void loadIntConst(int n) {
0197:                items.makeImmediateItem(syms.intType, n).load();
0198:            }
0199:
0200:            /** The opcode that loads a zero constant of a given type code.
0201:             *  @param tc   The given type code (@see ByteCode).
0202:             */
0203:            public static int zero(int tc) {
0204:                switch (tc) {
0205:                case INTcode:
0206:                case BYTEcode:
0207:                case SHORTcode:
0208:                case CHARcode:
0209:                    return iconst_0;
0210:                case LONGcode:
0211:                    return lconst_0;
0212:                case FLOATcode:
0213:                    return fconst_0;
0214:                case DOUBLEcode:
0215:                    return dconst_0;
0216:                default:
0217:                    throw new AssertionError("zero");
0218:                }
0219:            }
0220:
0221:            /** The opcode that loads a one constant of a given type code.
0222:             *  @param tc   The given type code (@see ByteCode).
0223:             */
0224:            public static int one(int tc) {
0225:                return zero(tc) + 1;
0226:            }
0227:
0228:            /** Generate code to load -1 of the given type code (either int or long).
0229:             *  @param tc   The given type code (@see ByteCode).
0230:             */
0231:            void emitMinusOne(int tc) {
0232:                if (tc == LONGcode) {
0233:                    items.makeImmediateItem(syms.longType, new Long(-1)).load();
0234:                } else {
0235:                    code.emitop0(iconst_m1);
0236:                }
0237:            }
0238:
0239:            /** Construct a symbol to reflect the qualifying type that should
0240:             *  appear in the byte code as per JLS 13.1.
0241:             *
0242:             *  For target >= 1.2: Clone a method with the qualifier as owner (except
0243:             *  for those cases where we need to work around VM bugs).
0244:             *
0245:             *  For target <= 1.1: If qualified variable or method is defined in a
0246:             *  non-accessible class, clone it with the qualifier class as owner.
0247:             *
0248:             *  @param sym    The accessed symbol
0249:             *  @param site   The qualifier's type.
0250:             */
0251:            Symbol binaryQualifier(Symbol sym, Type site) {
0252:
0253:                if (site.tag == ARRAY) {
0254:                    if (sym == syms.lengthVar || sym.owner != syms.arrayClass)
0255:                        return sym;
0256:                    // array clone can be qualified by the array type in later targets
0257:                    Symbol qualifier = target.arrayBinaryCompatibility() ? new ClassSymbol(
0258:                            Flags.PUBLIC, site.tsym.name, site, syms.noSymbol)
0259:                            : syms.objectType.tsym;
0260:                    return sym.clone(qualifier);
0261:                }
0262:
0263:                if (sym.owner == site.tsym
0264:                        || (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
0265:                    return sym;
0266:                }
0267:                if (!target.obeyBinaryCompatibility())
0268:                    return rs.isAccessible(attrEnv, (TypeSymbol) sym.owner) ? sym
0269:                            : sym.clone(site.tsym);
0270:
0271:                if (!target.interfaceFieldsBinaryCompatibility()) {
0272:                    if ((sym.owner.flags() & INTERFACE) != 0 && sym.kind == VAR)
0273:                        return sym;
0274:                }
0275:
0276:                // leave alone methods inherited from Object
0277:                // JLS2 13.1.
0278:                if (sym.owner == syms.objectType.tsym)
0279:                    return sym;
0280:
0281:                if (!target.interfaceObjectOverridesBinaryCompatibility()) {
0282:                    if ((sym.owner.flags() & INTERFACE) != 0
0283:                            && syms.objectType.tsym.members().lookup(sym.name).scope != null)
0284:                        return sym;
0285:                }
0286:
0287:                return sym.clone(site.tsym);
0288:            }
0289:
0290:            /** Insert a reference to given type in the constant pool,
0291:             *  checking for an array with too many dimensions;
0292:             *  return the reference's index.
0293:             *  @param type   The type for which a reference is inserted.
0294:             */
0295:            int makeRef(DiagnosticPosition pos, Type type) {
0296:                checkDimension(pos, type);
0297:                return pool.put(type.tag == CLASS ? (Object) type.tsym
0298:                        : (Object) type);
0299:            }
0300:
0301:            /** Check if the given type is an array with too many dimensions.
0302:             */
0303:            private void checkDimension(DiagnosticPosition pos, Type t) {
0304:                switch (t.tag) {
0305:                case METHOD:
0306:                    checkDimension(pos, t.getReturnType());
0307:                    for (List<Type> args = t.getParameterTypes(); args
0308:                            .nonEmpty(); args = args.tail)
0309:                        checkDimension(pos, args.head);
0310:                    break;
0311:                case ARRAY:
0312:                    if (types.dimensions(t) > ClassFile.MAX_DIMENSIONS) {
0313:                        log.error(pos, "limit.dimensions");
0314:                        nerrs++;
0315:                    }
0316:                    break;
0317:                default:
0318:                    break;
0319:                }
0320:            }
0321:
0322:            /** Create a tempory variable.
0323:             *  @param type   The variable's type.
0324:             */
0325:            LocalItem makeTemp(Type type) {
0326:                VarSymbol v = new VarSymbol(Flags.SYNTHETIC, names.empty, type,
0327:                        env.enclMethod.sym);
0328:                code.newLocal(v);
0329:                return items.makeLocalItem(v);
0330:            }
0331:
0332:            /** Generate code to call a non-private method or constructor.
0333:             *  @param pos         Position to be used for error reporting.
0334:             *  @param site        The type of which the method is a member.
0335:             *  @param name        The method's name.
0336:             *  @param argtypes    The method's argument types.
0337:             *  @param isStatic    A flag that indicates whether we call a
0338:             *                     static or instance method.
0339:             */
0340:            void callMethod(DiagnosticPosition pos, Type site, Name name,
0341:                    List<Type> argtypes, boolean isStatic) {
0342:                Symbol msym = rs.resolveInternalMethod(pos, attrEnv, site,
0343:                        name, argtypes, null);
0344:                if (isStatic)
0345:                    items.makeStaticItem(msym).invoke();
0346:                else
0347:                    items.makeMemberItem(msym, name == names.init).invoke();
0348:            }
0349:
0350:            /** Is the given method definition an access method
0351:             *  resulting from a qualified super? This is signified by an odd
0352:             *  access code.
0353:             */
0354:            private boolean isAccessSuper(JCMethodDecl enclMethod) {
0355:                return (enclMethod.mods.flags & SYNTHETIC) != 0
0356:                        && isOddAccessName(enclMethod.name);
0357:            }
0358:
0359:            /** Does given name start with "access$" and end in an odd digit?
0360:             */
0361:            private boolean isOddAccessName(Name name) {
0362:                return name.startsWith(accessDollar)
0363:                        && (name.byteAt(name.len - 1) & 1) == 1;
0364:            }
0365:
0366:            /* ************************************************************************
0367:             * Non-local exits
0368:             *************************************************************************/
0369:
0370:            /** Generate code to invoke the finalizer associated with given
0371:             *  environment.
0372:             *  Any calls to finalizers are appended to the environments `cont' chain.
0373:             *  Mark beginning of gap in catch all range for finalizer.
0374:             */
0375:            void genFinalizer(Env<GenContext> env) {
0376:                if (code.isAlive() && env.info.finalize != null)
0377:                    env.info.finalize.gen();
0378:            }
0379:
0380:            /** Generate code to call all finalizers of structures aborted by
0381:             *  a non-local
0382:             *  exit.  Return target environment of the non-local exit.
0383:             *  @param target      The tree representing the structure that's aborted
0384:             *  @param env         The environment current at the non-local exit.
0385:             */
0386:            Env<GenContext> unwind(JCTree target, Env<GenContext> env) {
0387:                Env<GenContext> env1 = env;
0388:                while (true) {
0389:                    genFinalizer(env1);
0390:                    if (env1.tree == target)
0391:                        break;
0392:                    env1 = env1.next;
0393:                }
0394:                return env1;
0395:            }
0396:
0397:            /** Mark end of gap in catch-all range for finalizer.
0398:             *  @param env   the environment which might contain the finalizer
0399:             *               (if it does, env.info.gaps != null).
0400:             */
0401:            void endFinalizerGap(Env<GenContext> env) {
0402:                if (env.info.gaps != null && env.info.gaps.length() % 2 == 1)
0403:                    env.info.gaps.append(code.curPc());
0404:            }
0405:
0406:            /** Mark end of all gaps in catch-all ranges for finalizers of environments
0407:             *  lying between, and including to two environments.
0408:             *  @param from    the most deeply nested environment to mark
0409:             *  @param to      the least deeply nested environment to mark
0410:             */
0411:            void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {
0412:                Env<GenContext> last = null;
0413:                while (last != to) {
0414:                    endFinalizerGap(from);
0415:                    last = from;
0416:                    from = from.next;
0417:                }
0418:            }
0419:
0420:            /** Do any of the structures aborted by a non-local exit have
0421:             *  finalizers that require an empty stack?
0422:             *  @param target      The tree representing the structure that's aborted
0423:             *  @param env         The environment current at the non-local exit.
0424:             */
0425:            boolean hasFinally(JCTree target, Env<GenContext> env) {
0426:                while (env.tree != target) {
0427:                    if (env.tree.getTag() == JCTree.TRY
0428:                            && env.info.finalize.hasFinalizer())
0429:                        return true;
0430:                    env = env.next;
0431:                }
0432:                return false;
0433:            }
0434:
0435:            /* ************************************************************************
0436:             * Normalizing class-members.
0437:             *************************************************************************/
0438:
0439:            /** Distribute member initializer code into constructors and <clinit>
0440:             *  method.
0441:             *  @param defs         The list of class member declarations.
0442:             *  @param c            The enclosing class.
0443:             */
0444:            List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
0445:                ListBuffer<JCStatement> initCode = new ListBuffer<JCStatement>();
0446:                ListBuffer<JCStatement> clinitCode = new ListBuffer<JCStatement>();
0447:                ListBuffer<JCTree> methodDefs = new ListBuffer<JCTree>();
0448:                // Sort definitions into three listbuffers:
0449:                //  - initCode for instance initializers
0450:                //  - clinitCode for class initializers
0451:                //  - methodDefs for method definitions
0452:                for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
0453:                    JCTree def = l.head;
0454:                    switch (def.getTag()) {
0455:                    case JCTree.BLOCK:
0456:                        JCBlock block = (JCBlock) def;
0457:                        if ((block.flags & STATIC) != 0)
0458:                            clinitCode.append(block);
0459:                        else
0460:                            initCode.append(block);
0461:                        break;
0462:                    case JCTree.METHODDEF:
0463:                        methodDefs.append(def);
0464:                        break;
0465:                    case JCTree.VARDEF:
0466:                        JCVariableDecl vdef = (JCVariableDecl) def;
0467:                        VarSymbol sym = vdef.sym;
0468:                        checkDimension(vdef.pos(), sym.type);
0469:                        if (vdef.init != null) {
0470:                            if ((sym.flags() & STATIC) == 0) {
0471:                                // Always initialize instance variables.
0472:                                JCStatement init = make.at(vdef.pos())
0473:                                        .Assignment(sym, vdef.init);
0474:                                initCode.append(init);
0475:                                if (endPositions != null) {
0476:                                    Integer endPos = endPositions.remove(vdef);
0477:                                    if (endPos != null)
0478:                                        endPositions.put(init, endPos);
0479:                                }
0480:                            } else if (sym.getConstValue() == null) {
0481:                                // Initialize class (static) variables only if
0482:                                // they are not compile-time constants.
0483:                                JCStatement init = make.at(vdef.pos)
0484:                                        .Assignment(sym, vdef.init);
0485:                                clinitCode.append(init);
0486:                                if (endPositions != null) {
0487:                                    Integer endPos = endPositions.remove(vdef);
0488:                                    if (endPos != null)
0489:                                        endPositions.put(init, endPos);
0490:                                }
0491:                            } else {
0492:                                checkStringConstant(vdef.init.pos(), sym
0493:                                        .getConstValue());
0494:                            }
0495:                        }
0496:                        break;
0497:                    default:
0498:                        assert false;
0499:                    }
0500:                }
0501:                // Insert any instance initializers into all constructors.
0502:                if (initCode.length() != 0) {
0503:                    List<JCStatement> inits = initCode.toList();
0504:                    for (JCTree t : methodDefs) {
0505:                        normalizeMethod((JCMethodDecl) t, inits);
0506:                    }
0507:                }
0508:                // If there are class initializers, create a <clinit> method
0509:                // that contains them as its body.
0510:                if (clinitCode.length() != 0) {
0511:                    MethodSymbol clinit = new MethodSymbol(STATIC,
0512:                            names.clinit, new MethodType(List.<Type> nil(),
0513:                                    syms.voidType, List.<Type> nil(),
0514:                                    syms.methodClass), c);
0515:                    c.members().enter(clinit);
0516:                    List<JCStatement> clinitStats = clinitCode.toList();
0517:                    JCBlock block = make.at(clinitStats.head.pos()).Block(0,
0518:                            clinitStats);
0519:                    block.endpos = TreeInfo.endPos(clinitStats.last());
0520:                    methodDefs.append(make.MethodDef(clinit, block));
0521:                }
0522:                // Return all method definitions.
0523:                return methodDefs.toList();
0524:            }
0525:
0526:            /** Check a constant value and report if it is a string that is
0527:             *  too large.
0528:             */
0529:            private void checkStringConstant(DiagnosticPosition pos,
0530:                    Object constValue) {
0531:                if (nerrs != 0
0532:                        || // only complain about a long string once
0533:                        constValue == null
0534:                        || !(constValue instanceof  String)
0535:                        || ((String) constValue).length() < Pool.MAX_STRING_LENGTH)
0536:                    return;
0537:                log.error(pos, "limit.string");
0538:                nerrs++;
0539:            }
0540:
0541:            /** Insert instance initializer code into initial constructor.
0542:             *  @param md        The tree potentially representing a
0543:             *                   constructor's definition.
0544:             *  @param initCode  The list of instance initializer statements.
0545:             */
0546:            void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode) {
0547:                if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
0548:                    // We are seeing a constructor that does not call another
0549:                    // constructor of the same class.
0550:                    List<JCStatement> stats = md.body.stats;
0551:                    ListBuffer<JCStatement> newstats = new ListBuffer<JCStatement>();
0552:
0553:                    if (stats.nonEmpty()) {
0554:                        // Copy initializers of synthetic variables generated in
0555:                        // the translation of inner classes.
0556:                        while (TreeInfo.isSyntheticInit(stats.head)) {
0557:                            newstats.append(stats.head);
0558:                            stats = stats.tail;
0559:                        }
0560:                        // Copy superclass constructor call
0561:                        newstats.append(stats.head);
0562:                        stats = stats.tail;
0563:                        // Copy remaining synthetic initializers.
0564:                        while (stats.nonEmpty()
0565:                                && TreeInfo.isSyntheticInit(stats.head)) {
0566:                            newstats.append(stats.head);
0567:                            stats = stats.tail;
0568:                        }
0569:                        // Now insert the initializer code.
0570:                        newstats.appendList(initCode);
0571:                        // And copy all remaining statements.
0572:                        while (stats.nonEmpty()) {
0573:                            newstats.append(stats.head);
0574:                            stats = stats.tail;
0575:                        }
0576:                    }
0577:                    md.body.stats = newstats.toList();
0578:                    if (md.body.endpos == Position.NOPOS)
0579:                        md.body.endpos = TreeInfo.endPos(md.body.stats.last());
0580:                }
0581:            }
0582:
0583:            /* ********************************************************************
0584:             * Adding miranda methods
0585:             *********************************************************************/
0586:
0587:            /** Add abstract methods for all methods defined in one of
0588:             *  the interfaces of a given class,
0589:             *  provided they are not already implemented in the class.
0590:             *
0591:             *  @param c      The class whose interfaces are searched for methods
0592:             *                for which Miranda methods should be added.
0593:             */
0594:            void implementInterfaceMethods(ClassSymbol c) {
0595:                implementInterfaceMethods(c, c);
0596:            }
0597:
0598:            /** Add abstract methods for all methods defined in one of
0599:             *  the interfaces of a given class,
0600:             *  provided they are not already implemented in the class.
0601:             *
0602:             *  @param c      The class whose interfaces are searched for methods
0603:             *                for which Miranda methods should be added.
0604:             *  @param site   The class in which a definition may be needed.
0605:             */
0606:            void implementInterfaceMethods(ClassSymbol c, ClassSymbol site) {
0607:                for (List<Type> l = types.interfaces(c.type); l.nonEmpty(); l = l.tail) {
0608:                    ClassSymbol i = (ClassSymbol) l.head.tsym;
0609:                    for (Scope.Entry e = i.members().elems; e != null; e = e.sibling) {
0610:                        if (e.sym.kind == MTH && (e.sym.flags() & STATIC) == 0) {
0611:                            MethodSymbol absMeth = (MethodSymbol) e.sym;
0612:                            MethodSymbol implMeth = absMeth
0613:                                    .binaryImplementation(site, types);
0614:                            if (implMeth == null)
0615:                                addAbstractMethod(site, absMeth);
0616:                            else if ((implMeth.flags() & IPROXY) != 0)
0617:                                adjustAbstractMethod(site, implMeth, absMeth);
0618:                        }
0619:                    }
0620:                    implementInterfaceMethods(i, site);
0621:                }
0622:            }
0623:
0624:            /** Add an abstract methods to a class
0625:             *  which implicitly implements a method defined in some interface
0626:             *  implemented by the class. These methods are called "Miranda methods".
0627:             *  Enter the newly created method into its enclosing class scope.
0628:             *  Note that it is not entered into the class tree, as the emitter
0629:             *  doesn't need to see it there to emit an abstract method.
0630:             *
0631:             *  @param c      The class to which the Miranda method is added.
0632:             *  @param m      The interface method symbol for which a Miranda method
0633:             *                is added.
0634:             */
0635:            private void addAbstractMethod(ClassSymbol c, MethodSymbol m) {
0636:                MethodSymbol absMeth = new MethodSymbol(m.flags() | IPROXY
0637:                        | SYNTHETIC, m.name, m.type, // was c.type.memberType(m), but now only !generics supported
0638:                        c);
0639:                c.members().enter(absMeth); // add to symbol table
0640:            }
0641:
0642:            private void adjustAbstractMethod(ClassSymbol c, MethodSymbol pm,
0643:                    MethodSymbol im) {
0644:                MethodType pmt = (MethodType) pm.type;
0645:                Type imt = types.memberType(c.type, im);
0646:                pmt.thrown = chk.intersect(pmt.getThrownTypes(), imt
0647:                        .getThrownTypes());
0648:            }
0649:
0650:            /* ************************************************************************
0651:             * Traversal methods
0652:             *************************************************************************/
0653:
0654:            /** Visitor argument: The current environment.
0655:             */
0656:            Env<GenContext> env;
0657:
0658:            /** Visitor argument: The expected type (prototype).
0659:             */
0660:            Type pt;
0661:
0662:            /** Visitor result: The item representing the computed value.
0663:             */
0664:            Item result;
0665:
0666:            /** Visitor method: generate code for a definition, catching and reporting
0667:             *  any completion failures.
0668:             *  @param tree    The definition to be visited.
0669:             *  @param env     The environment current at the definition.
0670:             */
0671:            public void genDef(JCTree tree, Env<GenContext> env) {
0672:                Env<GenContext> prevEnv = this .env;
0673:                try {
0674:                    this .env = env;
0675:                    tree.accept(this );
0676:                } catch (CompletionFailure ex) {
0677:                    chk.completionError(tree.pos(), ex);
0678:                } finally {
0679:                    this .env = prevEnv;
0680:                }
0681:            }
0682:
0683:            /** Derived visitor method: check whether CharacterRangeTable
0684:             *  should be emitted, if so, put a new entry into CRTable
0685:             *  and call method to generate bytecode.
0686:             *  If not, just call method to generate bytecode.
0687:             *  @see    #genStat(Tree, Env)
0688:             *
0689:             *  @param  tree     The tree to be visited.
0690:             *  @param  env      The environment to use.
0691:             *  @param  crtFlags The CharacterRangeTable flags
0692:             *                   indicating type of the entry.
0693:             */
0694:            public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {
0695:                if (!genCrt) {
0696:                    genStat(tree, env);
0697:                    return;
0698:                }
0699:                int startpc = code.curPc();
0700:                genStat(tree, env);
0701:                if (tree.getTag() == JCTree.BLOCK)
0702:                    crtFlags |= CRT_BLOCK;
0703:                code.crt.put(tree, crtFlags, startpc, code.curPc());
0704:            }
0705:
0706:            /** Derived visitor method: generate code for a statement.
0707:             */
0708:            public void genStat(JCTree tree, Env<GenContext> env) {
0709:                if (code.isAlive()) {
0710:                    code.statBegin(tree.pos);
0711:                    genDef(tree, env);
0712:                } else if (env.info.isSwitch && tree.getTag() == JCTree.VARDEF) {
0713:                    // variables whose declarations are in a switch
0714:                    // can be used even if the decl is unreachable.
0715:                    code.newLocal(((JCVariableDecl) tree).sym);
0716:                }
0717:            }
0718:
0719:            /** Derived visitor method: check whether CharacterRangeTable
0720:             *  should be emitted, if so, put a new entry into CRTable
0721:             *  and call method to generate bytecode.
0722:             *  If not, just call method to generate bytecode.
0723:             *  @see    #genStats(List, Env)
0724:             *
0725:             *  @param  trees    The list of trees to be visited.
0726:             *  @param  env      The environment to use.
0727:             *  @param  crtFlags The CharacterRangeTable flags
0728:             *                   indicating type of the entry.
0729:             */
0730:            public void genStats(List<JCStatement> trees, Env<GenContext> env,
0731:                    int crtFlags) {
0732:                if (!genCrt) {
0733:                    genStats(trees, env);
0734:                    return;
0735:                }
0736:                if (trees.length() == 1) { // mark one statement with the flags
0737:                    genStat(trees.head, env, crtFlags | CRT_STATEMENT);
0738:                } else {
0739:                    int startpc = code.curPc();
0740:                    genStats(trees, env);
0741:                    code.crt.put(trees, crtFlags, startpc, code.curPc());
0742:                }
0743:            }
0744:
0745:            /** Derived visitor method: generate code for a list of statements.
0746:             */
0747:            public void genStats(List<? extends JCTree> trees,
0748:                    Env<GenContext> env) {
0749:                for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
0750:                    genStat(l.head, env, CRT_STATEMENT);
0751:            }
0752:
0753:            /** Derived visitor method: check whether CharacterRangeTable
0754:             *  should be emitted, if so, put a new entry into CRTable
0755:             *  and call method to generate bytecode.
0756:             *  If not, just call method to generate bytecode.
0757:             *  @see    #genCond(Tree,boolean)
0758:             *
0759:             *  @param  tree     The tree to be visited.
0760:             *  @param  crtFlags The CharacterRangeTable flags
0761:             *                   indicating type of the entry.
0762:             */
0763:            public CondItem genCond(JCTree tree, int crtFlags) {
0764:                if (!genCrt)
0765:                    return genCond(tree, false);
0766:                int startpc = code.curPc();
0767:                CondItem item = genCond(tree,
0768:                        (crtFlags & CRT_FLOW_CONTROLLER) != 0);
0769:                code.crt.put(tree, crtFlags, startpc, code.curPc());
0770:                return item;
0771:            }
0772:
0773:            /** Derived visitor method: generate code for a boolean
0774:             *  expression in a control-flow context.
0775:             *  @param _tree         The expression to be visited.
0776:             *  @param markBranches The flag to indicate that the condition is
0777:             *                      a flow controller so produced conditions
0778:             *                      should contain a proper tree to generate
0779:             *                      CharacterRangeTable branches for them.
0780:             */
0781:            public CondItem genCond(JCTree _tree, boolean markBranches) {
0782:                JCTree inner_tree = TreeInfo.skipParens(_tree);
0783:                if (inner_tree.getTag() == JCTree.CONDEXPR) {
0784:                    JCConditional tree = (JCConditional) inner_tree;
0785:                    CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
0786:                    if (cond.isTrue()) {
0787:                        code.resolve(cond.trueJumps);
0788:                        CondItem result = genCond(tree.truepart,
0789:                                CRT_FLOW_TARGET);
0790:                        if (markBranches)
0791:                            result.tree = tree.truepart;
0792:                        return result;
0793:                    }
0794:                    if (cond.isFalse()) {
0795:                        code.resolve(cond.falseJumps);
0796:                        CondItem result = genCond(tree.falsepart,
0797:                                CRT_FLOW_TARGET);
0798:                        if (markBranches)
0799:                            result.tree = tree.falsepart;
0800:                        return result;
0801:                    }
0802:                    Chain secondJumps = cond.jumpFalse();
0803:                    code.resolve(cond.trueJumps);
0804:                    CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
0805:                    if (markBranches)
0806:                        first.tree = tree.truepart;
0807:                    Chain falseJumps = first.jumpFalse();
0808:                    code.resolve(first.trueJumps);
0809:                    Chain trueJumps = code.branch(goto_);
0810:                    code.resolve(secondJumps);
0811:                    CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);
0812:                    CondItem result = items.makeCondItem(second.opcode, code
0813:                            .mergeChains(trueJumps, second.trueJumps), code
0814:                            .mergeChains(falseJumps, second.falseJumps));
0815:                    if (markBranches)
0816:                        result.tree = tree.falsepart;
0817:                    return result;
0818:                } else {
0819:                    CondItem result = genExpr(_tree, syms.booleanType).mkCond();
0820:                    if (markBranches)
0821:                        result.tree = _tree;
0822:                    return result;
0823:                }
0824:            }
0825:
0826:            /** Visitor method: generate code for an expression, catching and reporting
0827:             *  any completion failures.
0828:             *  @param tree    The expression to be visited.
0829:             *  @param pt      The expression's expected type (proto-type).
0830:             */
0831:            public Item genExpr(JCTree tree, Type pt) {
0832:                Type prevPt = this .pt;
0833:                try {
0834:                    if (tree.type.constValue() != null) {
0835:                        // Short circuit any expressions which are constants
0836:                        checkStringConstant(tree.pos(), tree.type.constValue());
0837:                        result = items.makeImmediateItem(tree.type, tree.type
0838:                                .constValue());
0839:                    } else {
0840:                        this .pt = pt;
0841:                        tree.accept(this );
0842:                    }
0843:                    return result.coerce(pt);
0844:                } catch (CompletionFailure ex) {
0845:                    chk.completionError(tree.pos(), ex);
0846:                    code.state.stacksize = 1;
0847:                    return items.makeStackItem(pt);
0848:                } finally {
0849:                    this .pt = prevPt;
0850:                }
0851:            }
0852:
0853:            /** Derived visitor method: generate code for a list of method arguments.
0854:             *  @param trees    The argument expressions to be visited.
0855:             *  @param pts      The expression's expected types (i.e. the formal parameter
0856:             *                  types of the invoked method).
0857:             */
0858:            public void genArgs(List<JCExpression> trees, List<Type> pts) {
0859:                for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) {
0860:                    genExpr(l.head, pts.head).load();
0861:                    pts = pts.tail;
0862:                }
0863:                // require lists be of same length
0864:                assert pts.isEmpty();
0865:            }
0866:
0867:            /* ************************************************************************
0868:             * Visitor methods for statements and definitions
0869:             *************************************************************************/
0870:
0871:            /** Thrown when the byte code size exceeds limit.
0872:             */
0873:            public static class CodeSizeOverflow extends RuntimeException {
0874:                private static final long serialVersionUID = 0;
0875:
0876:                public CodeSizeOverflow() {
0877:                }
0878:            }
0879:
0880:            public void visitMethodDef(JCMethodDecl tree) {
0881:                // Create a new local environment that points pack at method
0882:                // definition.
0883:                Env<GenContext> localEnv = env.dup(tree);
0884:                localEnv.enclMethod = tree;
0885:
0886:                // The expected type of every return statement in this method
0887:                // is the method's return type.
0888:                this .pt = tree.sym.erasure(types).getReturnType();
0889:
0890:                checkDimension(tree.pos(), tree.sym.erasure(types));
0891:                genMethod(tree, localEnv, false);
0892:            }
0893:
0894:            //where
0895:            /** Generate code for a method.
0896:             *  @param tree     The tree representing the method definition.
0897:             *  @param env      The environment current for the method body.
0898:             *  @param fatcode  A flag that indicates whether all jumps are
0899:             *		    within 32K.  We first invoke this method under
0900:             *		    the assumption that fatcode == false, i.e. all
0901:             *		    jumps are within 32K.  If this fails, fatcode
0902:             *		    is set to true and we try again.
0903:             */
0904:            void genMethod(JCMethodDecl tree, Env<GenContext> env,
0905:                    boolean fatcode) {
0906:                MethodSymbol meth = tree.sym;
0907:                //    	System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG
0908:                if (Code.width(types.erasure(env.enclMethod.sym.type)
0909:                        .getParameterTypes())
0910:                        + (((tree.mods.flags & STATIC) == 0 || meth
0911:                                .isConstructor()) ? 1 : 0) > ClassFile.MAX_PARAMETERS) {
0912:                    log.error(tree.pos(), "limit.parameters");
0913:                    nerrs++;
0914:                }
0915:
0916:                else if (tree.body != null) {
0917:                    // Create a new code structure and initialize it.
0918:                    int startpcCrt = initCode(tree, env, fatcode);
0919:
0920:                    try {
0921:                        genStat(tree.body, env);
0922:                    } catch (CodeSizeOverflow e) {
0923:                        // Failed due to code limit, try again with jsr/ret
0924:                        startpcCrt = initCode(tree, env, fatcode);
0925:                        genStat(tree.body, env);
0926:                    }
0927:
0928:                    if (code.state.stacksize != 0) {
0929:                        log.error(tree.body.pos(), "stack.sim.error", tree);
0930:                        throw new AssertionError();
0931:                    }
0932:
0933:                    // If last statement could complete normally, insert a
0934:                    // return at the end.
0935:                    if (code.isAlive()) {
0936:                        code.statBegin(TreeInfo.endPos(tree.body));
0937:                        if (env.enclMethod == null
0938:                                || env.enclMethod.sym.type.getReturnType().tag == VOID) {
0939:                            code.emitop0(return_);
0940:                        } else {
0941:                            // sometime dead code seems alive (4415991);
0942:                            // generate a small loop instead
0943:                            int startpc = code.entryPoint();
0944:                            CondItem c = items.makeCondItem(goto_);
0945:                            code.resolve(c.jumpTrue(), startpc);
0946:                        }
0947:                    }
0948:                    if (genCrt)
0949:                        code.crt.put(tree.body, CRT_BLOCK, startpcCrt, code
0950:                                .curPc());
0951:
0952:                    // End the scope of all local variables in variable info.
0953:                    code.endScopes(0);
0954:
0955:                    // If we exceeded limits, panic
0956:                    if (code.checkLimits(tree.pos(), log)) {
0957:                        nerrs++;
0958:                        return;
0959:                    }
0960:
0961:                    // If we generated short code but got a long jump, do it again
0962:                    // with fatCode = true.
0963:                    if (!fatcode && code.fatcode)
0964:                        genMethod(tree, env, true);
0965:
0966:                    // Clean up
0967:                    if (stackMap == StackMapFormat.JSR202) {
0968:                        code.lastFrame = null;
0969:                        code.frameBeforeLast = null;
0970:                    }
0971:                }
0972:            }
0973:
0974:            private int initCode(JCMethodDecl tree, Env<GenContext> env,
0975:                    boolean fatcode) {
0976:                MethodSymbol meth = tree.sym;
0977:
0978:                // Create a new code structure.
0979:                meth.code = code = new Code(meth, fatcode,
0980:                        lineDebugInfo ? toplevel.lineMap : null, varDebugInfo,
0981:                        stackMap, debugCode, genCrt ? new CRTable(tree,
0982:                                env.toplevel.endPositions) : null, syms, types,
0983:                        pool);
0984:                items = new Items(pool, code, syms, types);
0985:                if (code.debugCode)
0986:                    System.err.println(meth + " for body " + tree);
0987:
0988:                // If method is not static, create a new local variable address
0989:                // for `this'.
0990:                if ((tree.mods.flags & STATIC) == 0) {
0991:                    Type selfType = meth.owner.type;
0992:                    if (meth.isConstructor() && selfType != syms.objectType)
0993:                        selfType = UninitializedType
0994:                                .uninitializedThis(selfType);
0995:                    code.setDefined(code.newLocal(new VarSymbol(FINAL,
0996:                            names._this , selfType, meth.owner)));
0997:                }
0998:
0999:                // Mark all parameters as defined from the beginning of
1000:                // the method.
1001:                for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1002:                    checkDimension(l.head.pos(), l.head.sym.type);
1003:                    code.setDefined(code.newLocal(l.head.sym));
1004:                }
1005:
1006:                // Get ready to generate code for method body.
1007:                int startpcCrt = genCrt ? code.curPc() : 0;
1008:                code.entryPoint();
1009:
1010:                // Suppress initial stackmap
1011:                code.pendingStackMap = false;
1012:
1013:                return startpcCrt;
1014:            }
1015:
1016:            public void visitVarDef(JCVariableDecl tree) {
1017:                VarSymbol v = tree.sym;
1018:                code.newLocal(v);
1019:                if (tree.init != null) {
1020:                    checkStringConstant(tree.init.pos(), v.getConstValue());
1021:                    if (v.getConstValue() == null || varDebugInfo) {
1022:                        genExpr(tree.init, v.erasure(types)).load();
1023:                        items.makeLocalItem(v).store();
1024:                    }
1025:                }
1026:                checkDimension(tree.pos(), v.type);
1027:            }
1028:
1029:            public void visitSkip(JCSkip tree) {
1030:            }
1031:
1032:            public void visitBlock(JCBlock tree) {
1033:                int limit = code.nextreg;
1034:                Env<GenContext> localEnv = env.dup(tree, new GenContext());
1035:                genStats(tree.stats, localEnv);
1036:                // End the scope of all block-local variables in variable info.
1037:                if (env.tree.getTag() != JCTree.METHODDEF) {
1038:                    code.statBegin(tree.endpos);
1039:                    code.endScopes(limit);
1040:                    code.pendingStatPos = Position.NOPOS;
1041:                }
1042:            }
1043:
1044:            public void visitDoLoop(JCDoWhileLoop tree) {
1045:                genLoop(tree, tree.body, tree.cond, List
1046:                        .<JCExpressionStatement> nil(), false);
1047:            }
1048:
1049:            public void visitWhileLoop(JCWhileLoop tree) {
1050:                genLoop(tree, tree.body, tree.cond, List
1051:                        .<JCExpressionStatement> nil(), true);
1052:            }
1053:
1054:            public void visitForLoop(JCForLoop tree) {
1055:                int limit = code.nextreg;
1056:                genStats(tree.init, env);
1057:                genLoop(tree, tree.body, tree.cond, tree.step, true);
1058:                code.endScopes(limit);
1059:            }
1060:
1061:            //where
1062:            /** Generate code for a loop.
1063:             *  @param loop       The tree representing the loop.
1064:             *  @param body       The loop's body.
1065:             *  @param cond       The loop's controling condition.
1066:             *  @param step       "Step" statements to be inserted at end of
1067:             *                    each iteration.
1068:             *  @param testFirst  True if the loop test belongs before the body.
1069:             */
1070:            private void genLoop(JCStatement loop, JCStatement body,
1071:                    JCExpression cond, List<JCExpressionStatement> step,
1072:                    boolean testFirst) {
1073:                Env<GenContext> loopEnv = env.dup(loop, new GenContext());
1074:                int startpc = code.entryPoint();
1075:                if (testFirst) {
1076:                    CondItem c;
1077:                    if (cond != null) {
1078:                        code.statBegin(cond.pos);
1079:                        c = genCond(TreeInfo.skipParens(cond),
1080:                                CRT_FLOW_CONTROLLER);
1081:                    } else {
1082:                        c = items.makeCondItem(goto_);
1083:                    }
1084:                    Chain loopDone = c.jumpFalse();
1085:                    code.resolve(c.trueJumps);
1086:                    genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1087:                    code.resolve(loopEnv.info.cont);
1088:                    genStats(step, loopEnv);
1089:                    code.resolve(code.branch(goto_), startpc);
1090:                    code.resolve(loopDone);
1091:                } else {
1092:                    genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1093:                    code.resolve(loopEnv.info.cont);
1094:                    genStats(step, loopEnv);
1095:                    CondItem c;
1096:                    if (cond != null) {
1097:                        code.statBegin(cond.pos);
1098:                        c = genCond(TreeInfo.skipParens(cond),
1099:                                CRT_FLOW_CONTROLLER);
1100:                    } else {
1101:                        c = items.makeCondItem(goto_);
1102:                    }
1103:                    code.resolve(c.jumpTrue(), startpc);
1104:                    code.resolve(c.falseJumps);
1105:                }
1106:                code.resolve(loopEnv.info.exit);
1107:            }
1108:
1109:            public void visitForeachLoop(JCEnhancedForLoop tree) {
1110:                throw new AssertionError(); // should have been removed by Lower.
1111:            }
1112:
1113:            public void visitLabelled(JCLabeledStatement tree) {
1114:                Env<GenContext> localEnv = env.dup(tree, new GenContext());
1115:                genStat(tree.body, localEnv, CRT_STATEMENT);
1116:                code.resolve(localEnv.info.exit);
1117:            }
1118:
1119:            public void visitSwitch(JCSwitch tree) {
1120:                int limit = code.nextreg;
1121:                assert tree.selector.type.tag != CLASS;
1122:                int startpcCrt = genCrt ? code.curPc() : 0;
1123:                Item sel = genExpr(tree.selector, syms.intType);
1124:                List<JCCase> cases = tree.cases;
1125:                if (cases.isEmpty()) {
1126:                    // We are seeing:  switch <sel> {}
1127:                    sel.load().drop();
1128:                    if (genCrt)
1129:                        code.crt.put(TreeInfo.skipParens(tree.selector),
1130:                                CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());
1131:                } else {
1132:                    // We are seeing a nonempty switch.
1133:                    sel.load();
1134:                    if (genCrt)
1135:                        code.crt.put(TreeInfo.skipParens(tree.selector),
1136:                                CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());
1137:                    Env<GenContext> switchEnv = env.dup(tree, new GenContext());
1138:                    switchEnv.info.isSwitch = true;
1139:
1140:                    // Compute number of labels and minimum and maximum label values.
1141:                    // For each case, store its label in an array.
1142:                    int lo = Integer.MAX_VALUE; // minimum label.
1143:                    int hi = Integer.MIN_VALUE; // maximum label.
1144:                    int nlabels = 0; // number of labels.
1145:
1146:                    int[] labels = new int[cases.length()]; // the label array.
1147:                    int defaultIndex = -1; // the index of the default clause.
1148:
1149:                    List<JCCase> l = cases;
1150:                    for (int i = 0; i < labels.length; i++) {
1151:                        if (l.head.pat != null) {
1152:                            int val = ((Number) l.head.pat.type.constValue())
1153:                                    .intValue();
1154:                            labels[i] = val;
1155:                            if (val < lo)
1156:                                lo = val;
1157:                            if (hi < val)
1158:                                hi = val;
1159:                            nlabels++;
1160:                        } else {
1161:                            assert defaultIndex == -1;
1162:                            defaultIndex = i;
1163:                        }
1164:                        l = l.tail;
1165:                    }
1166:
1167:                    // Determine whether to issue a tableswitch or a lookupswitch
1168:                    // instruction.
1169:                    long table_space_cost = 4 + ((long) hi - lo + 1); // words
1170:                    long table_time_cost = 3; // comparisons
1171:                    long lookup_space_cost = 3 + 2 * (long) nlabels;
1172:                    long lookup_time_cost = nlabels;
1173:                    int opcode = nlabels > 0
1174:                            && table_space_cost + 3 * table_time_cost <= lookup_space_cost
1175:                                    + 3 * lookup_time_cost ? tableswitch
1176:                            : lookupswitch;
1177:
1178:                    int startpc = code.curPc(); // the position of the selector operation
1179:                    code.emitop0(opcode);
1180:                    code.align(4);
1181:                    int tableBase = code.curPc(); // the start of the jump table
1182:                    int[] offsets = null; // a table of offsets for a lookupswitch
1183:                    code.emit4(-1); // leave space for default offset
1184:                    if (opcode == tableswitch) {
1185:                        code.emit4(lo); // minimum label
1186:                        code.emit4(hi); // maximum label
1187:                        for (long i = lo; i <= hi; i++) { // leave space for jump table
1188:                            code.emit4(-1);
1189:                        }
1190:                    } else {
1191:                        code.emit4(nlabels); // number of labels
1192:                        for (int i = 0; i < nlabels; i++) {
1193:                            code.emit4(-1);
1194:                            code.emit4(-1); // leave space for lookup table
1195:                        }
1196:                        offsets = new int[labels.length];
1197:                    }
1198:                    Code.State stateSwitch = code.state.dup();
1199:                    code.markDead();
1200:
1201:                    // For each case do:
1202:                    l = cases;
1203:                    for (int i = 0; i < labels.length; i++) {
1204:                        JCCase c = l.head;
1205:                        l = l.tail;
1206:
1207:                        int pc = code.entryPoint(stateSwitch);
1208:                        // Insert offset directly into code or else into the
1209:                        // offsets table.
1210:                        if (i != defaultIndex) {
1211:                            if (opcode == tableswitch) {
1212:                                code.put4(tableBase + 4 * (labels[i] - lo + 3),
1213:                                        pc - startpc);
1214:                            } else {
1215:                                offsets[i] = pc - startpc;
1216:                            }
1217:                        } else {
1218:                            code.put4(tableBase, pc - startpc);
1219:                        }
1220:
1221:                        // Generate code for the statements in this case.
1222:                        genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
1223:                    }
1224:
1225:                    // Resolve all breaks.
1226:                    code.resolve(switchEnv.info.exit);
1227:
1228:                    // If we have not set the default offset, we do so now.
1229:                    if (code.get4(tableBase) == -1) {
1230:                        code.put4(tableBase, code.entryPoint(stateSwitch)
1231:                                - startpc);
1232:                    }
1233:
1234:                    if (opcode == tableswitch) {
1235:                        // Let any unfilled slots point to the default case.
1236:                        int defaultOffset = code.get4(tableBase);
1237:                        for (long i = lo; i <= hi; i++) {
1238:                            int t = (int) (tableBase + 4 * (i - lo + 3));
1239:                            if (code.get4(t) == -1)
1240:                                code.put4(t, defaultOffset);
1241:                        }
1242:                    } else {
1243:                        // Sort non-default offsets and copy into lookup table.
1244:                        if (defaultIndex >= 0)
1245:                            for (int i = defaultIndex; i < labels.length - 1; i++) {
1246:                                labels[i] = labels[i + 1];
1247:                                offsets[i] = offsets[i + 1];
1248:                            }
1249:                        if (nlabels > 0)
1250:                            qsort2(labels, offsets, 0, nlabels - 1);
1251:                        for (int i = 0; i < nlabels; i++) {
1252:                            int caseidx = tableBase + 8 * (i + 1);
1253:                            code.put4(caseidx, labels[i]);
1254:                            code.put4(caseidx + 4, offsets[i]);
1255:                        }
1256:                    }
1257:                }
1258:                code.endScopes(limit);
1259:            }
1260:
1261:            //where
1262:            /** Sort (int) arrays of keys and values
1263:             */
1264:            static void qsort2(int[] keys, int[] values, int lo, int hi) {
1265:                int i = lo;
1266:                int j = hi;
1267:                int pivot = keys[(i + j) / 2];
1268:                do {
1269:                    while (keys[i] < pivot)
1270:                        i++;
1271:                    while (pivot < keys[j])
1272:                        j--;
1273:                    if (i <= j) {
1274:                        int temp1 = keys[i];
1275:                        keys[i] = keys[j];
1276:                        keys[j] = temp1;
1277:                        int temp2 = values[i];
1278:                        values[i] = values[j];
1279:                        values[j] = temp2;
1280:                        i++;
1281:                        j--;
1282:                    }
1283:                } while (i <= j);
1284:                if (lo < j)
1285:                    qsort2(keys, values, lo, j);
1286:                if (i < hi)
1287:                    qsort2(keys, values, i, hi);
1288:            }
1289:
1290:            public void visitSynchronized(JCSynchronized tree) {
1291:                int limit = code.nextreg;
1292:                // Generate code to evaluate lock and save in temporary variable.
1293:                final LocalItem lockVar = makeTemp(syms.objectType);
1294:                genExpr(tree.lock, tree.lock.type).load().duplicate();
1295:                lockVar.store();
1296:
1297:                // Generate code to enter monitor.
1298:                code.emitop0(monitorenter);
1299:                code.state.lock(lockVar.reg);
1300:
1301:                // Generate code for a try statement with given body, no catch clauses
1302:                // in a new environment with the "exit-monitor" operation as finalizer.
1303:                final Env<GenContext> syncEnv = env.dup(tree, new GenContext());
1304:                syncEnv.info.finalize = new GenFinalizer() {
1305:                    void gen() {
1306:                        genLast();
1307:                        assert syncEnv.info.gaps.length() % 2 == 0;
1308:                        syncEnv.info.gaps.append(code.curPc());
1309:                    }
1310:
1311:                    void genLast() {
1312:                        if (code.isAlive()) {
1313:                            lockVar.load();
1314:                            code.emitop0(monitorexit);
1315:                            code.state.unlock(lockVar.reg);
1316:                        }
1317:                    }
1318:                };
1319:                syncEnv.info.gaps = new ListBuffer<Integer>();
1320:                genTry(tree.body, List.<JCCatch> nil(), syncEnv);
1321:                code.endScopes(limit);
1322:            }
1323:
1324:            public void visitTry(final JCTry tree) {
1325:                // Generate code for a try statement with given body and catch clauses,
1326:                // in a new environment which calls the finally block if there is one.
1327:                final Env<GenContext> tryEnv = env.dup(tree, new GenContext());
1328:                final Env<GenContext> oldEnv = env;
1329:                if (!useJsrLocally) {
1330:                    useJsrLocally = (stackMap == StackMapFormat.NONE)
1331:                            && (jsrlimit <= 0 || jsrlimit < 100
1332:                                    && estimateCodeComplexity(tree.finalizer) > jsrlimit);
1333:                }
1334:                tryEnv.info.finalize = new GenFinalizer() {
1335:                    void gen() {
1336:                        if (useJsrLocally) {
1337:                            if (tree.finalizer != null) {
1338:                                Code.State jsrState = code.state.dup();
1339:                                jsrState.push(code.jsrReturnValue);
1340:                                tryEnv.info.cont = new Chain(
1341:                                        code.emitJump(jsr), tryEnv.info.cont,
1342:                                        jsrState);
1343:                            }
1344:                            assert tryEnv.info.gaps.length() % 2 == 0;
1345:                            tryEnv.info.gaps.append(code.curPc());
1346:                        } else {
1347:                            assert tryEnv.info.gaps.length() % 2 == 0;
1348:                            tryEnv.info.gaps.append(code.curPc());
1349:                            genLast();
1350:                        }
1351:                    }
1352:
1353:                    void genLast() {
1354:                        if (tree.finalizer != null)
1355:                            genStat(tree.finalizer, oldEnv, CRT_BLOCK);
1356:                    }
1357:
1358:                    boolean hasFinalizer() {
1359:                        return tree.finalizer != null;
1360:                    }
1361:                };
1362:                tryEnv.info.gaps = new ListBuffer<Integer>();
1363:                genTry(tree.body, tree.catchers, tryEnv);
1364:            }
1365:
1366:            //where
1367:            /** Generate code for a try or synchronized statement
1368:             *  @param body      The body of the try or synchronized statement.
1369:             *  @param catchers  The lis of catch clauses.
1370:             *  @param env       the environment current for the body.
1371:             */
1372:            void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {
1373:                int limit = code.nextreg;
1374:                int startpc = code.curPc();
1375:                Code.State stateTry = code.state.dup();
1376:                genStat(body, env, CRT_BLOCK);
1377:                int endpc = code.curPc();
1378:                boolean hasFinalizer = env.info.finalize != null
1379:                        && env.info.finalize.hasFinalizer();
1380:                List<Integer> gaps = env.info.gaps.toList();
1381:                code.statBegin(TreeInfo.endPos(body));
1382:                genFinalizer(env);
1383:                code.statBegin(TreeInfo.endPos(env.tree));
1384:                Chain exitChain = code.branch(goto_);
1385:                endFinalizerGap(env);
1386:                if (startpc != endpc)
1387:                    for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
1388:                        // start off with exception on stack
1389:                        code.entryPoint(stateTry, l.head.param.sym.type);
1390:                        genCatch(l.head, env, startpc, endpc, gaps);
1391:                        genFinalizer(env);
1392:                        if (hasFinalizer || l.tail.nonEmpty()) {
1393:                            code.statBegin(TreeInfo.endPos(env.tree));
1394:                            exitChain = code.mergeChains(exitChain, code
1395:                                    .branch(goto_));
1396:                        }
1397:                        endFinalizerGap(env);
1398:                    }
1399:                if (hasFinalizer) {
1400:                    // Create a new register segement to avoid allocating
1401:                    // the same variables in finalizers and other statements.
1402:                    code.newRegSegment();
1403:
1404:                    // Add a catch-all clause.
1405:
1406:                    // start off with exception on stack
1407:                    int catchallpc = code.entryPoint(stateTry,
1408:                            syms.throwableType);
1409:
1410:                    // Register all exception ranges for catch all clause.
1411:                    // The range of the catch all clause is from the beginning
1412:                    // of the try or synchronized block until the present
1413:                    // code pointer excluding all gaps in the current
1414:                    // environment's GenContext.
1415:                    int startseg = startpc;
1416:                    while (env.info.gaps.nonEmpty()) {
1417:                        int endseg = env.info.gaps.next().intValue();
1418:                        registerCatch(body.pos(), startseg, endseg, catchallpc,
1419:                                0);
1420:                        startseg = env.info.gaps.next().intValue();
1421:                    }
1422:                    code.statBegin(TreeInfo.finalizerPos(env.tree));
1423:                    code.markStatBegin();
1424:
1425:                    Item excVar = makeTemp(syms.throwableType);
1426:                    excVar.store();
1427:                    genFinalizer(env);
1428:                    excVar.load();
1429:                    registerCatch(body.pos(), startseg, env.info.gaps.next()
1430:                            .intValue(), catchallpc, 0);
1431:                    code.emitop0(athrow);
1432:                    code.markDead();
1433:
1434:                    // If there are jsr's to this finalizer, ...
1435:                    if (env.info.cont != null) {
1436:                        // Resolve all jsr's.
1437:                        code.resolve(env.info.cont);
1438:
1439:                        // Mark statement line number
1440:                        code.statBegin(TreeInfo.finalizerPos(env.tree));
1441:                        code.markStatBegin();
1442:
1443:                        // Save return address.
1444:                        LocalItem retVar = makeTemp(syms.throwableType);
1445:                        retVar.store();
1446:
1447:                        // Generate finalizer code.
1448:                        env.info.finalize.genLast();
1449:
1450:                        // Return.
1451:                        code.emitop1w(ret, retVar.reg);
1452:                        code.markDead();
1453:                    }
1454:                }
1455:
1456:                // Resolve all breaks.
1457:                code.resolve(exitChain);
1458:
1459:                // End the scopes of all try-local variables in variable info.
1460:                code.endScopes(limit);
1461:            }
1462:
1463:            /** Generate code for a catch clause.
1464:             *  @param tree     The catch clause.
1465:             *  @param env      The environment current in the enclosing try.
1466:             *  @param startpc  Start pc of try-block.
1467:             *  @param endpc    End pc of try-block.
1468:             */
1469:            void genCatch(JCCatch tree, Env<GenContext> env, int startpc,
1470:                    int endpc, List<Integer> gaps) {
1471:                if (startpc != endpc) {
1472:                    int catchType = makeRef(tree.pos(), tree.param.type);
1473:                    while (gaps.nonEmpty()) {
1474:                        int end = gaps.head.intValue();
1475:                        registerCatch(tree.pos(), startpc, end, code.curPc(),
1476:                                catchType);
1477:                        gaps = gaps.tail;
1478:                        startpc = gaps.head.intValue();
1479:                        gaps = gaps.tail;
1480:                    }
1481:                    if (startpc < endpc)
1482:                        registerCatch(tree.pos(), startpc, endpc, code.curPc(),
1483:                                catchType);
1484:                    VarSymbol exparam = tree.param.sym;
1485:                    code.statBegin(tree.pos);
1486:                    code.markStatBegin();
1487:                    int limit = code.nextreg;
1488:                    int exlocal = code.newLocal(exparam);
1489:                    items.makeLocalItem(exparam).store();
1490:                    code.statBegin(TreeInfo.firstStatPos(tree.body));
1491:                    genStat(tree.body, env, CRT_BLOCK);
1492:                    code.endScopes(limit);
1493:                    code.statBegin(TreeInfo.endPos(tree.body));
1494:                }
1495:            }
1496:
1497:            /** Register a catch clause in the "Exceptions" code-attribute.
1498:             */
1499:            void registerCatch(DiagnosticPosition pos, int startpc, int endpc,
1500:                    int handler_pc, int catch_type) {
1501:                if (startpc != endpc) {
1502:                    char startpc1 = (char) startpc;
1503:                    char endpc1 = (char) endpc;
1504:                    char handler_pc1 = (char) handler_pc;
1505:                    if (startpc1 == startpc && endpc1 == endpc
1506:                            && handler_pc1 == handler_pc) {
1507:                        code.addCatch(startpc1, endpc1, handler_pc1,
1508:                                (char) catch_type);
1509:                    } else {
1510:                        if (!useJsrLocally && !target.generateStackMapTable()) {
1511:                            useJsrLocally = true;
1512:                            throw new CodeSizeOverflow();
1513:                        } else {
1514:                            log.error(pos, "limit.code.too.large.for.try.stmt");
1515:                            nerrs++;
1516:                        }
1517:                    }
1518:                }
1519:            }
1520:
1521:            /** Very roughly estimate the number of instructions needed for
1522:             *  the given tree.
1523:             */
1524:            int estimateCodeComplexity(JCTree tree) {
1525:                if (tree == null)
1526:                    return 0;
1527:                class ComplexityScanner extends TreeScanner {
1528:                    int complexity = 0;
1529:
1530:                    public void scan(JCTree tree) {
1531:                        if (complexity > jsrlimit)
1532:                            return;
1533:                        super .scan(tree);
1534:                    }
1535:
1536:                    public void visitClassDef(JCClassDecl tree) {
1537:                    }
1538:
1539:                    public void visitDoLoop(JCDoWhileLoop tree) {
1540:                        super .visitDoLoop(tree);
1541:                        complexity++;
1542:                    }
1543:
1544:                    public void visitWhileLoop(JCWhileLoop tree) {
1545:                        super .visitWhileLoop(tree);
1546:                        complexity++;
1547:                    }
1548:
1549:                    public void visitForLoop(JCForLoop tree) {
1550:                        super .visitForLoop(tree);
1551:                        complexity++;
1552:                    }
1553:
1554:                    public void visitSwitch(JCSwitch tree) {
1555:                        super .visitSwitch(tree);
1556:                        complexity += 5;
1557:                    }
1558:
1559:                    public void visitCase(JCCase tree) {
1560:                        super .visitCase(tree);
1561:                        complexity++;
1562:                    }
1563:
1564:                    public void visitSynchronized(JCSynchronized tree) {
1565:                        super .visitSynchronized(tree);
1566:                        complexity += 6;
1567:                    }
1568:
1569:                    public void visitTry(JCTry tree) {
1570:                        super .visitTry(tree);
1571:                        if (tree.finalizer != null)
1572:                            complexity += 6;
1573:                    }
1574:
1575:                    public void visitCatch(JCCatch tree) {
1576:                        super .visitCatch(tree);
1577:                        complexity += 2;
1578:                    }
1579:
1580:                    public void visitConditional(JCConditional tree) {
1581:                        super .visitConditional(tree);
1582:                        complexity += 2;
1583:                    }
1584:
1585:                    public void visitIf(JCIf tree) {
1586:                        super .visitIf(tree);
1587:                        complexity += 2;
1588:                    }
1589:
1590:                    // note: for break, continue, and return we don't take unwind() into account.
1591:                    public void visitBreak(JCBreak tree) {
1592:                        super .visitBreak(tree);
1593:                        complexity += 1;
1594:                    }
1595:
1596:                    public void visitContinue(JCContinue tree) {
1597:                        super .visitContinue(tree);
1598:                        complexity += 1;
1599:                    }
1600:
1601:                    public void visitReturn(JCReturn tree) {
1602:                        super .visitReturn(tree);
1603:                        complexity += 1;
1604:                    }
1605:
1606:                    public void visitThrow(JCThrow tree) {
1607:                        super .visitThrow(tree);
1608:                        complexity += 1;
1609:                    }
1610:
1611:                    public void visitAssert(JCAssert tree) {
1612:                        super .visitAssert(tree);
1613:                        complexity += 5;
1614:                    }
1615:
1616:                    public void visitApply(JCMethodInvocation tree) {
1617:                        super .visitApply(tree);
1618:                        complexity += 2;
1619:                    }
1620:
1621:                    public void visitNewClass(JCNewClass tree) {
1622:                        scan(tree.encl);
1623:                        scan(tree.args);
1624:                        complexity += 2;
1625:                    }
1626:
1627:                    public void visitNewArray(JCNewArray tree) {
1628:                        super .visitNewArray(tree);
1629:                        complexity += 5;
1630:                    }
1631:
1632:                    public void visitAssign(JCAssign tree) {
1633:                        super .visitAssign(tree);
1634:                        complexity += 1;
1635:                    }
1636:
1637:                    public void visitAssignop(JCAssignOp tree) {
1638:                        super .visitAssignop(tree);
1639:                        complexity += 2;
1640:                    }
1641:
1642:                    public void visitUnary(JCUnary tree) {
1643:                        complexity += 1;
1644:                        if (tree.type.constValue() == null)
1645:                            super .visitUnary(tree);
1646:                    }
1647:
1648:                    public void visitBinary(JCBinary tree) {
1649:                        complexity += 1;
1650:                        if (tree.type.constValue() == null)
1651:                            super .visitBinary(tree);
1652:                    }
1653:
1654:                    public void visitTypeTest(JCInstanceOf tree) {
1655:                        super .visitTypeTest(tree);
1656:                        complexity += 1;
1657:                    }
1658:
1659:                    public void visitIndexed(JCArrayAccess tree) {
1660:                        super .visitIndexed(tree);
1661:                        complexity += 1;
1662:                    }
1663:
1664:                    public void visitSelect(JCFieldAccess tree) {
1665:                        super .visitSelect(tree);
1666:                        if (tree.sym.kind == VAR)
1667:                            complexity += 1;
1668:                    }
1669:
1670:                    public void visitIdent(JCIdent tree) {
1671:                        if (tree.sym.kind == VAR) {
1672:                            complexity += 1;
1673:                            if (tree.type.constValue() == null
1674:                                    && tree.sym.owner.kind == TYP)
1675:                                complexity += 1;
1676:                        }
1677:                    }
1678:
1679:                    public void visitLiteral(JCLiteral tree) {
1680:                        complexity += 1;
1681:                    }
1682:
1683:                    public void visitTree(JCTree tree) {
1684:                    }
1685:
1686:                    public void visitWildcard(JCWildcard tree) {
1687:                        throw new AssertionError(this .getClass().getName());
1688:                    }
1689:                }
1690:                ComplexityScanner scanner = new ComplexityScanner();
1691:                tree.accept(scanner);
1692:                return scanner.complexity;
1693:            }
1694:
1695:            public void visitIf(JCIf tree) {
1696:                int limit = code.nextreg;
1697:                Chain thenExit = null;
1698:                CondItem c = genCond(TreeInfo.skipParens(tree.cond),
1699:                        CRT_FLOW_CONTROLLER);
1700:                Chain elseChain = c.jumpFalse();
1701:                if (!c.isFalse()) {
1702:                    code.resolve(c.trueJumps);
1703:                    genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1704:                    thenExit = code.branch(goto_);
1705:                }
1706:                if (elseChain != null) {
1707:                    code.resolve(elseChain);
1708:                    if (tree.elsepart != null)
1709:                        genStat(tree.elsepart, env, CRT_STATEMENT
1710:                                | CRT_FLOW_TARGET);
1711:                }
1712:                code.resolve(thenExit);
1713:                code.endScopes(limit);
1714:            }
1715:
1716:            public void visitExec(JCExpressionStatement tree) {
1717:                // Optimize x++ to ++x and x-- to --x.
1718:                JCExpression e = tree.expr;
1719:                switch (e.getTag()) {
1720:                case JCTree.POSTINC:
1721:                    ((JCUnary) e).setTag(JCTree.PREINC);
1722:                    break;
1723:                case JCTree.POSTDEC:
1724:                    ((JCUnary) e).setTag(JCTree.PREDEC);
1725:                    break;
1726:                }
1727:                genExpr(tree.expr, tree.expr.type).drop();
1728:            }
1729:
1730:            public void visitBreak(JCBreak tree) {
1731:                Env<GenContext> targetEnv = unwind(tree.target, env);
1732:                assert code.state.stacksize == 0;
1733:                targetEnv.info.addExit(code.branch(goto_));
1734:                endFinalizerGaps(env, targetEnv);
1735:            }
1736:
1737:            public void visitContinue(JCContinue tree) {
1738:                Env<GenContext> targetEnv = unwind(tree.target, env);
1739:                assert code.state.stacksize == 0;
1740:                targetEnv.info.addCont(code.branch(goto_));
1741:                endFinalizerGaps(env, targetEnv);
1742:            }
1743:
1744:            public void visitReturn(JCReturn tree) {
1745:                int limit = code.nextreg;
1746:                final Env<GenContext> targetEnv;
1747:                if (tree.expr != null) {
1748:                    Item r = genExpr(tree.expr, pt).load();
1749:                    if (hasFinally(env.enclMethod, env)) {
1750:                        r = makeTemp(pt);
1751:                        r.store();
1752:                    }
1753:                    targetEnv = unwind(env.enclMethod, env);
1754:                    r.load();
1755:                    code.emitop0(ireturn + Code.truncate(Code.typecode(pt)));
1756:                } else {
1757:                    targetEnv = unwind(env.enclMethod, env);
1758:                    code.emitop0(return_);
1759:                }
1760:                endFinalizerGaps(env, targetEnv);
1761:                code.endScopes(limit);
1762:            }
1763:
1764:            public void visitThrow(JCThrow tree) {
1765:                genExpr(tree.expr, tree.expr.type).load();
1766:                code.emitop0(athrow);
1767:            }
1768:
1769:            /* ************************************************************************
1770:             * Visitor methods for expressions
1771:             *************************************************************************/
1772:
1773:            public void visitApply(JCMethodInvocation tree) {
1774:                // Generate code for method.
1775:                Item m = genExpr(tree.meth, methodType);
1776:                // Generate code for all arguments, where the expected types are
1777:                // the parameters of the method's external type (that is, any implicit
1778:                // outer instance of a super(...) call appears as first parameter).
1779:                genArgs(tree.args, TreeInfo.symbol(tree.meth).externalType(
1780:                        types).getParameterTypes());
1781:                result = m.invoke();
1782:            }
1783:
1784:            public void visitConditional(JCConditional tree) {
1785:                Chain thenExit = null;
1786:                CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER);
1787:                Chain elseChain = c.jumpFalse();
1788:                if (!c.isFalse()) {
1789:                    code.resolve(c.trueJumps);
1790:                    int startpc = genCrt ? code.curPc() : 0;
1791:                    genExpr(tree.truepart, pt).load();
1792:                    code.state.forceStackTop(tree.type);
1793:                    if (genCrt)
1794:                        code.crt.put(tree.truepart, CRT_FLOW_TARGET, startpc,
1795:                                code.curPc());
1796:                    thenExit = code.branch(goto_);
1797:                }
1798:                if (elseChain != null) {
1799:                    code.resolve(elseChain);
1800:                    int startpc = genCrt ? code.curPc() : 0;
1801:                    genExpr(tree.falsepart, pt).load();
1802:                    code.state.forceStackTop(tree.type);
1803:                    if (genCrt)
1804:                        code.crt.put(tree.falsepart, CRT_FLOW_TARGET, startpc,
1805:                                code.curPc());
1806:                }
1807:                code.resolve(thenExit);
1808:                result = items.makeStackItem(pt);
1809:            }
1810:
1811:            public void visitNewClass(JCNewClass tree) {
1812:                // Enclosing instances or anonymous classes should have been eliminated
1813:                // by now.
1814:                assert tree.encl == null && tree.def == null;
1815:
1816:                code.emitop2(new_, makeRef(tree.pos(), tree.type));
1817:                code.emitop0(dup);
1818:
1819:                // Generate code for all arguments, where the expected types are
1820:                // the parameters of the constructor's external type (that is,
1821:                // any implicit outer instance appears as first parameter).
1822:                genArgs(tree.args, tree.constructor.externalType(types)
1823:                        .getParameterTypes());
1824:
1825:                items.makeMemberItem(tree.constructor, true).invoke();
1826:                result = items.makeStackItem(tree.type);
1827:            }
1828:
1829:            public void visitNewArray(JCNewArray tree) {
1830:                if (tree.elems != null) {
1831:                    Type elemtype = types.elemtype(tree.type);
1832:                    loadIntConst(tree.elems.length());
1833:                    Item arr = makeNewArray(tree.pos(), tree.type, 1);
1834:                    int i = 0;
1835:                    for (List<JCExpression> l = tree.elems; l.nonEmpty(); l = l.tail) {
1836:                        arr.duplicate();
1837:                        loadIntConst(i);
1838:                        i++;
1839:                        genExpr(l.head, elemtype).load();
1840:                        items.makeIndexedItem(elemtype).store();
1841:                    }
1842:                    result = arr;
1843:                } else {
1844:                    for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
1845:                        genExpr(l.head, syms.intType).load();
1846:                    }
1847:                    result = makeNewArray(tree.pos(), tree.type, tree.dims
1848:                            .length());
1849:                }
1850:            }
1851:
1852:            //where
1853:            /** Generate code to create an array with given element type and number
1854:             *  of dimensions.
1855:             */
1856:            Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
1857:                Type elemtype = types.elemtype(type);
1858:                if (types.dimensions(elemtype) + ndims > ClassFile.MAX_DIMENSIONS) {
1859:                    log.error(pos, "limit.dimensions");
1860:                    nerrs++;
1861:                }
1862:                int elemcode = Code.arraycode(elemtype);
1863:                if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
1864:                    code.emitAnewarray(makeRef(pos, elemtype), type);
1865:                } else if (elemcode == 1) {
1866:                    code.emitMultianewarray(ndims, makeRef(pos, type), type);
1867:                } else {
1868:                    code.emitNewarray(elemcode, type);
1869:                }
1870:                return items.makeStackItem(type);
1871:            }
1872:
1873:            public void visitParens(JCParens tree) {
1874:                result = genExpr(tree.expr, tree.expr.type);
1875:            }
1876:
1877:            public void visitAssign(JCAssign tree) {
1878:                Item l = genExpr(tree.lhs, tree.lhs.type);
1879:                genExpr(tree.rhs, tree.lhs.type).load();
1880:                result = items.makeAssignItem(l);
1881:            }
1882:
1883:            public void visitAssignop(JCAssignOp tree) {
1884:                OperatorSymbol operator = (OperatorSymbol) tree.operator;
1885:                Item l;
1886:                if (operator.opcode == string_add) {
1887:                    // Generate code to make a string buffer
1888:                    makeStringBuffer(tree.pos());
1889:
1890:                    // Generate code for first string, possibly save one
1891:                    // copy under buffer
1892:                    l = genExpr(tree.lhs, tree.lhs.type);
1893:                    if (l.width() > 0) {
1894:                        code.emitop0(dup_x1 + 3 * (l.width() - 1));
1895:                    }
1896:
1897:                    // Load first string and append to buffer.
1898:                    l.load();
1899:                    appendString(tree.lhs);
1900:
1901:                    // Append all other strings to buffer.
1902:                    appendStrings(tree.rhs);
1903:
1904:                    // Convert buffer to string.
1905:                    bufferToString(tree.pos());
1906:                } else {
1907:                    // Generate code for first expression
1908:                    l = genExpr(tree.lhs, tree.lhs.type);
1909:
1910:                    // If we have an increment of -32768 to +32767 of a local
1911:                    // int variable we can use an incr instruction instead of
1912:                    // proceeding further.
1913:                    if ((tree.getTag() == JCTree.PLUS_ASG || tree.getTag() == JCTree.MINUS_ASG)
1914:                            && l instanceof  LocalItem
1915:                            && tree.lhs.type.tag <= INT
1916:                            && tree.rhs.type.tag <= INT
1917:                            && tree.rhs.type.constValue() != null) {
1918:                        int ival = ((Number) tree.rhs.type.constValue())
1919:                                .intValue();
1920:                        if (tree.getTag() == JCTree.MINUS_ASG)
1921:                            ival = -ival;
1922:                        ((LocalItem) l).incr(ival);
1923:                        result = l;
1924:                        return;
1925:                    }
1926:                    // Otherwise, duplicate expression, load one copy
1927:                    // and complete binary operation.
1928:                    l.duplicate();
1929:                    l.coerce(operator.type.getParameterTypes().head).load();
1930:                    completeBinop(tree.lhs, tree.rhs, operator).coerce(
1931:                            tree.lhs.type);
1932:                }
1933:                result = items.makeAssignItem(l);
1934:            }
1935:
1936:            public void visitUnary(JCUnary tree) {
1937:                OperatorSymbol operator = (OperatorSymbol) tree.operator;
1938:                if (tree.getTag() == JCTree.NOT) {
1939:                    CondItem od = genCond(tree.arg, false);
1940:                    result = od.negate();
1941:                } else {
1942:                    Item od = genExpr(tree.arg, operator.type
1943:                            .getParameterTypes().head);
1944:                    switch (tree.getTag()) {
1945:                    case JCTree.POS:
1946:                        result = od.load();
1947:                        break;
1948:                    case JCTree.NEG:
1949:                        result = od.load();
1950:                        code.emitop0(operator.opcode);
1951:                        break;
1952:                    case JCTree.COMPL:
1953:                        result = od.load();
1954:                        emitMinusOne(od.typecode);
1955:                        code.emitop0(operator.opcode);
1956:                        break;
1957:                    case JCTree.PREINC:
1958:                    case JCTree.PREDEC:
1959:                        od.duplicate();
1960:                        if (od instanceof  LocalItem
1961:                                && (operator.opcode == iadd || operator.opcode == isub)) {
1962:                            ((LocalItem) od)
1963:                                    .incr(tree.getTag() == JCTree.PREINC ? 1
1964:                                            : -1);
1965:                            result = od;
1966:                        } else {
1967:                            od.load();
1968:                            code.emitop0(one(od.typecode));
1969:                            code.emitop0(operator.opcode);
1970:                            // Perform narrowing primitive conversion if byte,
1971:                            // char, or short.  Fix for 4304655.
1972:                            if (od.typecode != INTcode
1973:                                    && Code.truncate(od.typecode) == INTcode)
1974:                                code.emitop0(int2byte + od.typecode - BYTEcode);
1975:                            result = items.makeAssignItem(od);
1976:                        }
1977:                        break;
1978:                    case JCTree.POSTINC:
1979:                    case JCTree.POSTDEC:
1980:                        od.duplicate();
1981:                        if (od instanceof  LocalItem
1982:                                && (operator.opcode == iadd || operator.opcode == isub)) {
1983:                            Item res = od.load();
1984:                            ((LocalItem) od)
1985:                                    .incr(tree.getTag() == JCTree.POSTINC ? 1
1986:                                            : -1);
1987:                            result = res;
1988:                        } else {
1989:                            Item res = od.load();
1990:                            od.stash(od.typecode);
1991:                            code.emitop0(one(od.typecode));
1992:                            code.emitop0(operator.opcode);
1993:                            // Perform narrowing primitive conversion if byte,
1994:                            // char, or short.  Fix for 4304655.
1995:                            if (od.typecode != INTcode
1996:                                    && Code.truncate(od.typecode) == INTcode)
1997:                                code.emitop0(int2byte + od.typecode - BYTEcode);
1998:                            od.store();
1999:                            result = res;
2000:                        }
2001:                        break;
2002:                    case JCTree.NULLCHK:
2003:                        result = od.load();
2004:                        code.emitop0(dup);
2005:                        genNullCheck(tree.pos());
2006:                        break;
2007:                    default:
2008:                        assert false;
2009:                    }
2010:                }
2011:            }
2012:
2013:            /** Generate a null check from the object value at stack top. */
2014:            private void genNullCheck(DiagnosticPosition pos) {
2015:                callMethod(pos, syms.objectType, names.getClass, List
2016:                        .<Type> nil(), false);
2017:                code.emitop0(pop);
2018:            }
2019:
2020:            public void visitBinary(JCBinary tree) {
2021:                OperatorSymbol operator = (OperatorSymbol) tree.operator;
2022:                if (operator.opcode == string_add) {
2023:                    // Create a string buffer.
2024:                    makeStringBuffer(tree.pos());
2025:                    // Append all strings to buffer.
2026:                    appendStrings(tree);
2027:                    // Convert buffer to string.
2028:                    bufferToString(tree.pos());
2029:                    result = items.makeStackItem(syms.stringType);
2030:                } else if (tree.getTag() == JCTree.AND) {
2031:                    CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2032:                    if (!lcond.isFalse()) {
2033:                        Chain falseJumps = lcond.jumpFalse();
2034:                        code.resolve(lcond.trueJumps);
2035:                        CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2036:                        result = items.makeCondItem(rcond.opcode,
2037:                                rcond.trueJumps, code.mergeChains(falseJumps,
2038:                                        rcond.falseJumps));
2039:                    } else {
2040:                        result = lcond;
2041:                    }
2042:                } else if (tree.getTag() == JCTree.OR) {
2043:                    CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2044:                    if (!lcond.isTrue()) {
2045:                        Chain trueJumps = lcond.jumpTrue();
2046:                        code.resolve(lcond.falseJumps);
2047:                        CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2048:                        result = items.makeCondItem(rcond.opcode, code
2049:                                .mergeChains(trueJumps, rcond.trueJumps),
2050:                                rcond.falseJumps);
2051:                    } else {
2052:                        result = lcond;
2053:                    }
2054:                } else {
2055:                    Item od = genExpr(tree.lhs, operator.type
2056:                            .getParameterTypes().head);
2057:                    od.load();
2058:                    result = completeBinop(tree.lhs, tree.rhs, operator);
2059:                }
2060:            }
2061:
2062:            //where
2063:            /** Make a new string buffer.
2064:             */
2065:            void makeStringBuffer(DiagnosticPosition pos) {
2066:                code.emitop2(new_, makeRef(pos, stringBufferType));
2067:                code.emitop0(dup);
2068:                callMethod(pos, stringBufferType, names.init,
2069:                        List.<Type> nil(), false);
2070:            }
2071:
2072:            /** Append value (on tos) to string buffer (on tos - 1).
2073:             */
2074:            void appendString(JCTree tree) {
2075:                Type t = tree.type.baseType();
2076:                if (t.tag > lastBaseTag && t.tsym != syms.stringType.tsym) {
2077:                    t = syms.objectType;
2078:                }
2079:                items.makeMemberItem(getStringBufferAppend(tree, t), false)
2080:                        .invoke();
2081:            }
2082:
2083:            Symbol getStringBufferAppend(JCTree tree, Type t) {
2084:                assert t.constValue() == null;
2085:                Symbol method = stringBufferAppend.get(t);
2086:                if (method == null) {
2087:                    method = rs.resolveInternalMethod(tree.pos(), attrEnv,
2088:                            stringBufferType, names.append, List.of(t), null);
2089:                    stringBufferAppend.put(t, method);
2090:                }
2091:                return method;
2092:            }
2093:
2094:            /** Add all strings in tree to string buffer.
2095:             */
2096:            void appendStrings(JCTree tree) {
2097:                tree = TreeInfo.skipParens(tree);
2098:                if (tree.getTag() == JCTree.PLUS
2099:                        && tree.type.constValue() == null) {
2100:                    JCBinary op = (JCBinary) tree;
2101:                    if (op.operator.kind == MTH
2102:                            && ((OperatorSymbol) op.operator).opcode == string_add) {
2103:                        appendStrings(op.lhs);
2104:                        appendStrings(op.rhs);
2105:                        return;
2106:                    }
2107:                }
2108:                genExpr(tree, tree.type).load();
2109:                appendString(tree);
2110:            }
2111:
2112:            /** Convert string buffer on tos to string.
2113:             */
2114:            void bufferToString(DiagnosticPosition pos) {
2115:                callMethod(pos, stringBufferType, names.toString, List
2116:                        .<Type> nil(), false);
2117:            }
2118:
2119:            /** Complete generating code for operation, with left operand
2120:             *  already on stack.
2121:             *  @param lhs       The tree representing the left operand.
2122:             *  @param rhs       The tree representing the right operand.
2123:             *  @param operator  The operator symbol.
2124:             */
2125:            Item completeBinop(JCTree lhs, JCTree rhs, OperatorSymbol operator) {
2126:                MethodType optype = (MethodType) operator.type;
2127:                int opcode = operator.opcode;
2128:                if (opcode >= if_icmpeq && opcode <= if_icmple
2129:                        && rhs.type.constValue() instanceof  Number
2130:                        && ((Number) rhs.type.constValue()).intValue() == 0) {
2131:                    opcode = opcode + (ifeq - if_icmpeq);
2132:                } else if (opcode >= if_acmpeq && opcode <= if_acmpne
2133:                        && TreeInfo.isNull(rhs)) {
2134:                    opcode = opcode + (if_acmp_null - if_acmpeq);
2135:                } else {
2136:                    // The expected type of the right operand is
2137:                    // the second parameter type of the operator, except for
2138:                    // shifts with long shiftcount, where we convert the opcode
2139:                    // to a short shift and the expected type to int.
2140:                    Type rtype = operator.erasure(types).getParameterTypes().tail.head;
2141:                    if (opcode >= ishll && opcode <= lushrl) {
2142:                        opcode = opcode + (ishl - ishll);
2143:                        rtype = syms.intType;
2144:                    }
2145:                    // Generate code for right operand and load.
2146:                    genExpr(rhs, rtype).load();
2147:                    // If there are two consecutive opcode instructions,
2148:                    // emit the first now.
2149:                    if (opcode >= (1 << preShift)) {
2150:                        code.emitop0(opcode >> preShift);
2151:                        opcode = opcode & 0xFF;
2152:                    }
2153:                }
2154:                if (opcode >= ifeq && opcode <= if_acmpne
2155:                        || opcode == if_acmp_null || opcode == if_acmp_nonnull) {
2156:                    return items.makeCondItem(opcode);
2157:                } else {
2158:                    code.emitop0(opcode);
2159:                    return items.makeStackItem(optype.restype);
2160:                }
2161:            }
2162:
2163:            public void visitTypeCast(JCTypeCast tree) {
2164:                result = genExpr(tree.expr, tree.clazz.type).load();
2165:                // Additional code is only needed if we cast to a reference type
2166:                // which is not statically a supertype of the expression's type.
2167:                // For basic types, the coerce(...) in genExpr(...) will do
2168:                // the conversion.
2169:                if (tree.clazz.type.tag > lastBaseTag
2170:                        && types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
2171:                    code.emitop2(checkcast,
2172:                            makeRef(tree.pos(), tree.clazz.type));
2173:                }
2174:            }
2175:
2176:            public void visitWildcard(JCWildcard tree) {
2177:                throw new AssertionError(this .getClass().getName());
2178:            }
2179:
2180:            public void visitTypeTest(JCInstanceOf tree) {
2181:                genExpr(tree.expr, tree.expr.type).load();
2182:                code.emitop2(instanceof _, makeRef(tree.pos(), tree.clazz.type));
2183:                result = items.makeStackItem(syms.booleanType);
2184:            }
2185:
2186:            public void visitIndexed(JCArrayAccess tree) {
2187:                genExpr(tree.indexed, tree.indexed.type).load();
2188:                genExpr(tree.index, syms.intType).load();
2189:                result = items.makeIndexedItem(tree.type);
2190:            }
2191:
2192:            public void visitIdent(JCIdent tree) {
2193:                Symbol sym = tree.sym;
2194:                if (tree.name == names._this  || tree.name == names._super ) {
2195:                    Item res = tree.name == names._this  ? items.makeThisItem()
2196:                            : items.makeSuperItem();
2197:                    if (sym.kind == MTH) {
2198:                        // Generate code to address the constructor.
2199:                        res.load();
2200:                        res = items.makeMemberItem(sym, true);
2201:                    }
2202:                    result = res;
2203:                } else if (sym.kind == VAR && sym.owner.kind == MTH) {
2204:                    result = items.makeLocalItem((VarSymbol) sym);
2205:                } else if ((sym.flags() & STATIC) != 0) {
2206:                    if (!isAccessSuper(env.enclMethod))
2207:                        sym = binaryQualifier(sym, env.enclClass.type);
2208:                    result = items.makeStaticItem(sym);
2209:                } else {
2210:                    items.makeThisItem().load();
2211:                    sym = binaryQualifier(sym, env.enclClass.type);
2212:                    result = items.makeMemberItem(sym,
2213:                            (sym.flags() & PRIVATE) != 0);
2214:                }
2215:            }
2216:
2217:            public void visitSelect(JCFieldAccess tree) {
2218:                Symbol sym = tree.sym;
2219:
2220:                if (tree.name == names._class) {
2221:                    assert target.hasClassLiterals();
2222:                    code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type));
2223:                    result = items.makeStackItem(pt);
2224:                    return;
2225:                }
2226:
2227:                Symbol ssym = TreeInfo.symbol(tree.selected);
2228:
2229:                // Are we selecting via super?
2230:                boolean selectSuper = ssym != null
2231:                        && (ssym.kind == TYP || ssym.name == names._super );
2232:
2233:                // Are we accessing a member of the superclass in an access method
2234:                // resulting from a qualified super?
2235:                boolean accessSuper = isAccessSuper(env.enclMethod);
2236:
2237:                Item base = (selectSuper) ? items.makeSuperItem() : genExpr(
2238:                        tree.selected, tree.selected.type);
2239:
2240:                if (sym.kind == VAR
2241:                        && ((VarSymbol) sym).getConstValue() != null) {
2242:                    // We are seeing a variable that is constant but its selecting
2243:                    // expression is not.
2244:                    if ((sym.flags() & STATIC) != 0) {
2245:                        if (!selectSuper && (ssym == null || ssym.kind != TYP))
2246:                            base = base.load();
2247:                        base.drop();
2248:                    } else {
2249:                        base.load();
2250:                        genNullCheck(tree.selected.pos());
2251:                    }
2252:                    result = items.makeImmediateItem(sym.type,
2253:                            ((VarSymbol) sym).getConstValue());
2254:                } else {
2255:                    if (!accessSuper)
2256:                        sym = binaryQualifier(sym, tree.selected.type);
2257:                    if ((sym.flags() & STATIC) != 0) {
2258:                        if (!selectSuper && (ssym == null || ssym.kind != TYP))
2259:                            base = base.load();
2260:                        base.drop();
2261:                        result = items.makeStaticItem(sym);
2262:                    } else {
2263:                        base.load();
2264:                        if (sym == syms.lengthVar) {
2265:                            code.emitop0(arraylength);
2266:                            result = items.makeStackItem(syms.intType);
2267:                        } else {
2268:                            result = items.makeMemberItem(sym,
2269:                                    (sym.flags() & PRIVATE) != 0 || selectSuper
2270:                                            || accessSuper);
2271:                        }
2272:                    }
2273:                }
2274:            }
2275:
2276:            public void visitLiteral(JCLiteral tree) {
2277:                if (tree.type.tag == TypeTags.BOT) {
2278:                    code.emitop0(aconst_null);
2279:                    if (types.dimensions(pt) > 1) {
2280:                        code.emitop2(checkcast, makeRef(tree.pos(), pt));
2281:                        result = items.makeStackItem(pt);
2282:                    } else {
2283:                        result = items.makeStackItem(tree.type);
2284:                    }
2285:                } else
2286:                    result = items.makeImmediateItem(tree.type, tree.value);
2287:            }
2288:
2289:            public void visitLetExpr(LetExpr tree) {
2290:                int limit = code.nextreg;
2291:                genStats(tree.defs, env);
2292:                result = genExpr(tree.expr, tree.expr.type).load();
2293:                code.endScopes(limit);
2294:            }
2295:
2296:            /* ************************************************************************
2297:             * main method
2298:             *************************************************************************/
2299:
2300:            /** Generate code for a class definition.
2301:             *  @param env   The attribution environment that belongs to the
2302:             *               outermost class containing this class definition.
2303:             *               We need this for resolving some additional symbols.
2304:             *  @param cdef  The tree representing the class definition.
2305:             *  @return      True if code is generated with no errors.
2306:             */
2307:            public boolean genClass(Env<AttrContext> env, JCClassDecl cdef) {
2308:                try {
2309:                    attrEnv = env;
2310:                    ClassSymbol c = cdef.sym;
2311:                    this .toplevel = env.toplevel;
2312:                    this .endPositions = toplevel.endPositions;
2313:                    // If this is a class definition requiring Miranda methods,
2314:                    // add them.
2315:                    if (generateIproxies
2316:                            && (c.flags() & (INTERFACE | ABSTRACT)) == ABSTRACT
2317:                            && !allowGenerics // no Miranda methods available with generics
2318:                    )
2319:                        implementInterfaceMethods(c);
2320:                    cdef.defs = normalizeDefs(cdef.defs, c);
2321:                    c.pool = pool;
2322:                    pool.reset();
2323:                    Env<GenContext> localEnv = new Env<GenContext>(cdef,
2324:                            new GenContext());
2325:                    localEnv.toplevel = env.toplevel;
2326:                    localEnv.enclClass = cdef;
2327:                    for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2328:                        genDef(l.head, localEnv);
2329:                    }
2330:                    if (pool.numEntries() > Pool.MAX_ENTRIES) {
2331:                        log.error(cdef.pos(), "limit.pool");
2332:                        nerrs++;
2333:                    }
2334:                    if (nerrs != 0) {
2335:                        // if errors, discard code
2336:                        for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2337:                            if (l.head.getTag() == JCTree.METHODDEF)
2338:                                ((JCMethodDecl) l.head).sym.code = null;
2339:                        }
2340:                    }
2341:                    cdef.defs = List.nil(); // discard trees
2342:                    return nerrs == 0;
2343:                } finally {
2344:                    // note: this method does NOT support recursion.
2345:                    attrEnv = null;
2346:                    this .env = null;
2347:                    toplevel = null;
2348:                    endPositions = null;
2349:                    nerrs = 0;
2350:                }
2351:            }
2352:
2353:            /* ************************************************************************
2354:             * Auxiliary classes
2355:             *************************************************************************/
2356:
2357:            /** An abstract class for finalizer generation.
2358:             */
2359:            abstract class GenFinalizer {
2360:                /** Generate code to clean up when unwinding. */
2361:                abstract void gen();
2362:
2363:                /** Generate code to clean up at last. */
2364:                abstract void genLast();
2365:
2366:                /** Does this finalizer have some nontrivial cleanup to perform? */
2367:                boolean hasFinalizer() {
2368:                    return true;
2369:                }
2370:            }
2371:
2372:            /** code generation contexts,
2373:             *  to be used as type parameter for environments.
2374:             */
2375:            static class GenContext {
2376:
2377:                /** A chain for all unresolved jumps that exit the current environment.
2378:                 */
2379:                Chain exit = null;
2380:
2381:                /** A chain for all unresolved jumps that continue in the
2382:                 *  current environment.
2383:                 */
2384:                Chain cont = null;
2385:
2386:                /** A closure that generates the finalizer of the current environment.
2387:                 *  Only set for Synchronized and Try contexts.
2388:                 */
2389:                GenFinalizer finalize = null;
2390:
2391:                /** Is this a switch statement?  If so, allocate registers
2392:                 * even when the variable declaration is unreachable.
2393:                 */
2394:                boolean isSwitch = false;
2395:
2396:                /** A list buffer containing all gaps in the finalizer range,
2397:                 *  where a catch all exception should not apply.
2398:                 */
2399:                ListBuffer<Integer> gaps = null;
2400:
2401:                /** Add given chain to exit chain.
2402:                 */
2403:                void addExit(Chain c) {
2404:                    exit = Code.mergeChains(c, exit);
2405:                }
2406:
2407:                /** Add given chain to cont chain.
2408:                 */
2409:                void addCont(Chain c) {
2410:                    cont = Code.mergeChains(c, cont);
2411:                }
2412:            }
2413:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.