Source Code Cross Referenced for ClassWriter.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-2006 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.io.*;
0029:        import java.util.*;
0030:        import java.util.Set;
0031:        import java.util.HashSet;
0032:
0033:        import javax.tools.JavaFileManager;
0034:        import javax.tools.FileObject;
0035:        import javax.tools.JavaFileObject;
0036:
0037:        import com.sun.tools.javac.code.*;
0038:        import com.sun.tools.javac.code.Symbol.*;
0039:        import com.sun.tools.javac.code.Type.*;
0040:        import com.sun.tools.javac.util.*;
0041:        import com.sun.tools.javac.util.List;
0042:
0043:        import static com.sun.tools.javac.code.BoundKind.*;
0044:        import static com.sun.tools.javac.code.Flags.*;
0045:        import static com.sun.tools.javac.code.Kinds.*;
0046:        import static com.sun.tools.javac.code.TypeTags.*;
0047:        import static com.sun.tools.javac.jvm.UninitializedType.*;
0048:        import static javax.tools.StandardLocation.CLASS_OUTPUT;
0049:
0050:        /** This class provides operations to map an internal symbol table graph
0051:         *  rooted in a ClassSymbol into a classfile.
0052:         *
0053:         *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
0054:         *  you write code that depends on this, you do so at your own risk.
0055:         *  This code and its internal interfaces are subject to change or
0056:         *  deletion without notice.</b>
0057:         */
0058:        @Version("@(#)ClassWriter.java	1.131 07/07/20")
0059:        public class ClassWriter extends ClassFile {
0060:            protected static final Context.Key<ClassWriter> classWriterKey = new Context.Key<ClassWriter>();
0061:
0062:            private final Symtab syms;
0063:
0064:            private final Options options;
0065:
0066:            /** Switch: verbose output.
0067:             */
0068:            private boolean verbose;
0069:
0070:            /** Switch: scrable private names.
0071:             */
0072:            private boolean scramble;
0073:
0074:            /** Switch: scrable private names.
0075:             */
0076:            private boolean scrambleAll;
0077:
0078:            /** Switch: retrofit mode.
0079:             */
0080:            private boolean retrofit;
0081:
0082:            /** Switch: emit source file attribute.
0083:             */
0084:            private boolean emitSourceFile;
0085:
0086:            /** Switch: generate CharacterRangeTable attribute.
0087:             */
0088:            private boolean genCrt;
0089:
0090:            /** Switch: describe the generated stackmap
0091:             */
0092:            boolean debugstackmap;
0093:
0094:            /**
0095:             * Target class version.
0096:             */
0097:            private Target target;
0098:
0099:            /**
0100:             * Source language version.
0101:             */
0102:            private Source source;
0103:
0104:            /** Type utilities. */
0105:            private Types types;
0106:
0107:            /** The initial sizes of the data and constant pool buffers.
0108:             *  sizes are increased when buffers get full.
0109:             */
0110:            static final int DATA_BUF_SIZE = 0x0fff0;
0111:            static final int POOL_BUF_SIZE = 0x1fff0;
0112:
0113:            /** An output buffer for member info.
0114:             */
0115:            ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
0116:
0117:            /** An output buffer for the constant pool.
0118:             */
0119:            ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
0120:
0121:            /** An output buffer for type signatures.
0122:             */
0123:            ByteBuffer sigbuf = new ByteBuffer();
0124:
0125:            /** The constant pool.
0126:             */
0127:            Pool pool;
0128:
0129:            /** The inner classes to be written, as a set.
0130:             */
0131:            Set<ClassSymbol> innerClasses;
0132:
0133:            /** The inner classes to be written, as a queue where
0134:             *  enclosing classes come first.
0135:             */
0136:            ListBuffer<ClassSymbol> innerClassesQueue;
0137:
0138:            /** The log to use for verbose output.
0139:             */
0140:            private final Log log;
0141:
0142:            /** The name table. */
0143:            private final Name.Table names;
0144:
0145:            /** Access to files. */
0146:            private final JavaFileManager fileManager;
0147:
0148:            /** The tags and constants used in compressed stackmap. */
0149:            static final int SAME_FRAME_SIZE = 64;
0150:            static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
0151:            static final int SAME_FRAME_EXTENDED = 251;
0152:            static final int FULL_FRAME = 255;
0153:            static final int MAX_LOCAL_LENGTH_DIFF = 4;
0154:
0155:            /** Get the ClassWriter instance for this context. */
0156:            public static ClassWriter instance(Context context) {
0157:                ClassWriter instance = context.get(classWriterKey);
0158:                if (instance == null)
0159:                    instance = new ClassWriter(context);
0160:                return instance;
0161:            }
0162:
0163:            /** Construct a class writer, given an options table.
0164:             */
0165:            private ClassWriter(Context context) {
0166:                context.put(classWriterKey, this );
0167:
0168:                log = Log.instance(context);
0169:                names = Name.Table.instance(context);
0170:                syms = Symtab.instance(context);
0171:                options = Options.instance(context);
0172:                target = Target.instance(context);
0173:                source = Source.instance(context);
0174:                types = Types.instance(context);
0175:                fileManager = context.get(JavaFileManager.class);
0176:
0177:                verbose = options.get("-verbose") != null;
0178:                scramble = options.get("-scramble") != null;
0179:                scrambleAll = options.get("-scrambleAll") != null;
0180:                retrofit = options.get("-retrofit") != null;
0181:                genCrt = options.get("-Xjcov") != null;
0182:                debugstackmap = options.get("debugstackmap") != null;
0183:
0184:                emitSourceFile = options.get("-g:") == null
0185:                        || options.get("-g:source") != null;
0186:
0187:                String dumpModFlags = options.get("dumpmodifiers");
0188:                dumpClassModifiers = (dumpModFlags != null && dumpModFlags
0189:                        .indexOf('c') != -1);
0190:                dumpFieldModifiers = (dumpModFlags != null && dumpModFlags
0191:                        .indexOf('f') != -1);
0192:                dumpInnerClassModifiers = (dumpModFlags != null && dumpModFlags
0193:                        .indexOf('i') != -1);
0194:                dumpMethodModifiers = (dumpModFlags != null && dumpModFlags
0195:                        .indexOf('m') != -1);
0196:            }
0197:
0198:            /******************************************************************
0199:             * Diagnostics: dump generated class names and modifiers
0200:             ******************************************************************/
0201:
0202:            /** Value of option 'dumpmodifiers' is a string
0203:             *  indicating which modifiers should be dumped for debugging:
0204:             *    'c' -- classes
0205:             *    'f' -- fields
0206:             *    'i' -- innerclass attributes
0207:             *    'm' -- methods
0208:             *  For example, to dump everything:
0209:             *    javac -XDdumpmodifiers=cifm MyProg.java
0210:             */
0211:            private final boolean dumpClassModifiers; // -XDdumpmodifiers=c
0212:            private final boolean dumpFieldModifiers; // -XDdumpmodifiers=f
0213:            private final boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i
0214:            private final boolean dumpMethodModifiers; // -XDdumpmodifiers=m
0215:
0216:            /** Return flags as a string, separated by " ".
0217:             */
0218:            public static String flagNames(long flags) {
0219:                StringBuffer sbuf = new StringBuffer();
0220:                int i = 0;
0221:                long f = flags & StandardFlags;
0222:                while (f != 0) {
0223:                    if ((f & 1) != 0)
0224:                        sbuf.append(" " + flagName[i]);
0225:                    f = f >> 1;
0226:                    i++;
0227:                }
0228:                return sbuf.toString();
0229:            }
0230:
0231:            //where
0232:            private final static String[] flagName = { "PUBLIC", "PRIVATE",
0233:                    "PROTECTED", "STATIC", "FINAL", "SUPER", "VOLATILE",
0234:                    "TRANSIENT", "NATIVE", "INTERFACE", "ABSTRACT", "STRICTFP" };
0235:
0236:            /******************************************************************
0237:             * Output routines
0238:             ******************************************************************/
0239:
0240:            /** Write a character into given byte buffer;
0241:             *  byte buffer will not be grown.
0242:             */
0243:            void putChar(ByteBuffer buf, int op, int x) {
0244:                buf.elems[op] = (byte) ((x >> 8) & 0xFF);
0245:                buf.elems[op + 1] = (byte) ((x) & 0xFF);
0246:            }
0247:
0248:            /** Write an integer into given byte buffer;
0249:             *  byte buffer will not be grown.
0250:             */
0251:            void putInt(ByteBuffer buf, int adr, int x) {
0252:                buf.elems[adr] = (byte) ((x >> 24) & 0xFF);
0253:                buf.elems[adr + 1] = (byte) ((x >> 16) & 0xFF);
0254:                buf.elems[adr + 2] = (byte) ((x >> 8) & 0xFF);
0255:                buf.elems[adr + 3] = (byte) ((x) & 0xFF);
0256:            }
0257:
0258:            /******************************************************************
0259:             * Signature Generation
0260:             ******************************************************************/
0261:
0262:            /** Assemble signature of given type in string buffer.
0263:             */
0264:            void assembleSig(Type type) {
0265:                switch (type.tag) {
0266:                case BYTE:
0267:                    sigbuf.appendByte('B');
0268:                    break;
0269:                case SHORT:
0270:                    sigbuf.appendByte('S');
0271:                    break;
0272:                case CHAR:
0273:                    sigbuf.appendByte('C');
0274:                    break;
0275:                case INT:
0276:                    sigbuf.appendByte('I');
0277:                    break;
0278:                case LONG:
0279:                    sigbuf.appendByte('J');
0280:                    break;
0281:                case FLOAT:
0282:                    sigbuf.appendByte('F');
0283:                    break;
0284:                case DOUBLE:
0285:                    sigbuf.appendByte('D');
0286:                    break;
0287:                case BOOLEAN:
0288:                    sigbuf.appendByte('Z');
0289:                    break;
0290:                case VOID:
0291:                    sigbuf.appendByte('V');
0292:                    break;
0293:                case CLASS:
0294:                    sigbuf.appendByte('L');
0295:                    assembleClassSig(type);
0296:                    sigbuf.appendByte(';');
0297:                    break;
0298:                case ARRAY:
0299:                    ArrayType at = (ArrayType) type;
0300:                    sigbuf.appendByte('[');
0301:                    assembleSig(at.elemtype);
0302:                    break;
0303:                case METHOD:
0304:                    MethodType mt = (MethodType) type;
0305:                    sigbuf.appendByte('(');
0306:                    assembleSig(mt.argtypes);
0307:                    sigbuf.appendByte(')');
0308:                    assembleSig(mt.restype);
0309:                    if (hasTypeVar(mt.thrown)) {
0310:                        for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
0311:                            sigbuf.appendByte('^');
0312:                            assembleSig(l.head);
0313:                        }
0314:                    }
0315:                    break;
0316:                case WILDCARD: {
0317:                    WildcardType ta = (WildcardType) type;
0318:                    switch (ta.kind) {
0319:                    case SUPER:
0320:                        sigbuf.appendByte('-');
0321:                        assembleSig(ta.type);
0322:                        break;
0323:                    case EXTENDS:
0324:                        sigbuf.appendByte('+');
0325:                        assembleSig(ta.type);
0326:                        break;
0327:                    case UNBOUND:
0328:                        sigbuf.appendByte('*');
0329:                        break;
0330:                    default:
0331:                        throw new AssertionError(ta.kind);
0332:                    }
0333:                    break;
0334:                }
0335:                case TYPEVAR:
0336:                    sigbuf.appendByte('T');
0337:                    sigbuf.appendName(type.tsym.name);
0338:                    sigbuf.appendByte(';');
0339:                    break;
0340:                case FORALL:
0341:                    ForAll ft = (ForAll) type;
0342:                    assembleParamsSig(ft.tvars);
0343:                    assembleSig(ft.qtype);
0344:                    break;
0345:                case UNINITIALIZED_THIS:
0346:                case UNINITIALIZED_OBJECT:
0347:                    // we don't yet have a spec for uninitialized types in the
0348:                    // local variable table
0349:                    assembleSig(types.erasure(((UninitializedType) type).qtype));
0350:                    break;
0351:                default:
0352:                    throw new AssertionError("typeSig " + type.tag);
0353:                }
0354:            }
0355:
0356:            boolean hasTypeVar(List<Type> l) {
0357:                while (l.nonEmpty()) {
0358:                    if (l.head.tag == TypeTags.TYPEVAR)
0359:                        return true;
0360:                    l = l.tail;
0361:                }
0362:                return false;
0363:            }
0364:
0365:            void assembleClassSig(Type type) {
0366:                ClassType ct = (ClassType) type;
0367:                ClassSymbol c = (ClassSymbol) ct.tsym;
0368:                enterInner(c);
0369:                Type outer = ct.getEnclosingType();
0370:                if (outer.allparams().nonEmpty()) {
0371:                    boolean rawOuter = c.owner.kind == MTH || // either a local class
0372:                            c.name == names.empty; // or anonymous
0373:                    assembleClassSig(rawOuter ? types.erasure(outer) : outer);
0374:                    sigbuf.appendByte('.');
0375:                    assert c.flatname.startsWith(c.owner.enclClass().flatname);
0376:                    sigbuf.appendName(rawOuter ? c.flatname.subName(c.owner
0377:                            .enclClass().flatname.len + 1, c.flatname.len)
0378:                            : c.name);
0379:                } else {
0380:                    sigbuf.appendBytes(externalize(c.flatname));
0381:                }
0382:                if (ct.getTypeArguments().nonEmpty()) {
0383:                    sigbuf.appendByte('<');
0384:                    assembleSig(ct.getTypeArguments());
0385:                    sigbuf.appendByte('>');
0386:                }
0387:            }
0388:
0389:            void assembleSig(List<Type> types) {
0390:                for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail)
0391:                    assembleSig(ts.head);
0392:            }
0393:
0394:            void assembleParamsSig(List<Type> typarams) {
0395:                sigbuf.appendByte('<');
0396:                for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
0397:                    TypeVar tvar = (TypeVar) ts.head;
0398:                    sigbuf.appendName(tvar.tsym.name);
0399:                    List<Type> bounds = types.getBounds(tvar);
0400:                    if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
0401:                        sigbuf.appendByte(':');
0402:                    }
0403:                    for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
0404:                        sigbuf.appendByte(':');
0405:                        assembleSig(l.head);
0406:                    }
0407:                }
0408:                sigbuf.appendByte('>');
0409:            }
0410:
0411:            /** Return signature of given type
0412:             */
0413:            Name typeSig(Type type) {
0414:                assert sigbuf.length == 0;
0415:                //- System.out.println(" ? " + type);
0416:                assembleSig(type);
0417:                Name n = sigbuf.toName(names);
0418:                sigbuf.reset();
0419:                //- System.out.println("   " + n);
0420:                return n;
0421:            }
0422:
0423:            /** Given a type t, return the extended class name of its erasure in
0424:             *  external representation.
0425:             */
0426:            public Name xClassName(Type t) {
0427:                if (t.tag == CLASS) {
0428:                    return names.fromUtf(externalize(t.tsym.flatName()));
0429:                } else if (t.tag == ARRAY) {
0430:                    return typeSig(types.erasure(t));
0431:                } else {
0432:                    throw new AssertionError("xClassName");
0433:                }
0434:            }
0435:
0436:            /******************************************************************
0437:             * Writing the Constant Pool
0438:             ******************************************************************/
0439:
0440:            /** Thrown when the constant pool is over full.
0441:             */
0442:            public static class PoolOverflow extends Exception {
0443:                private static final long serialVersionUID = 0;
0444:
0445:                public PoolOverflow() {
0446:                }
0447:            }
0448:
0449:            public static class StringOverflow extends Exception {
0450:                private static final long serialVersionUID = 0;
0451:                public final String value;
0452:
0453:                public StringOverflow(String s) {
0454:                    value = s;
0455:                }
0456:            }
0457:
0458:            /** Write constant pool to pool buffer.
0459:             *  Note: during writing, constant pool
0460:             *  might grow since some parts of constants still need to be entered.
0461:             */
0462:            void writePool(Pool pool) throws PoolOverflow, StringOverflow {
0463:                int poolCountIdx = poolbuf.length;
0464:                poolbuf.appendChar(0);
0465:                int i = 1;
0466:                while (i < pool.pp) {
0467:                    Object value = pool.pool[i];
0468:                    assert value != null;
0469:                    if (value instanceof  Pool.Method)
0470:                        value = ((Pool.Method) value).m;
0471:                    else if (value instanceof  Pool.Variable)
0472:                        value = ((Pool.Variable) value).v;
0473:
0474:                    if (value instanceof  MethodSymbol) {
0475:                        MethodSymbol m = (MethodSymbol) value;
0476:                        poolbuf
0477:                                .appendByte((m.owner.flags() & INTERFACE) != 0 ? CONSTANT_InterfaceMethodref
0478:                                        : CONSTANT_Methodref);
0479:                        poolbuf.appendChar(pool.put(m.owner));
0480:                        poolbuf.appendChar(pool.put(nameType(m)));
0481:                    } else if (value instanceof  VarSymbol) {
0482:                        VarSymbol v = (VarSymbol) value;
0483:                        poolbuf.appendByte(CONSTANT_Fieldref);
0484:                        poolbuf.appendChar(pool.put(v.owner));
0485:                        poolbuf.appendChar(pool.put(nameType(v)));
0486:                    } else if (value instanceof  Name) {
0487:                        poolbuf.appendByte(CONSTANT_Utf8);
0488:                        byte[] bs = ((Name) value).toUtf();
0489:                        poolbuf.appendChar(bs.length);
0490:                        poolbuf.appendBytes(bs, 0, bs.length);
0491:                        if (bs.length > Pool.MAX_STRING_LENGTH)
0492:                            throw new StringOverflow(value.toString());
0493:                    } else if (value instanceof  ClassSymbol) {
0494:                        ClassSymbol c = (ClassSymbol) value;
0495:                        if (c.owner.kind == TYP)
0496:                            pool.put(c.owner);
0497:                        poolbuf.appendByte(CONSTANT_Class);
0498:                        if (c.type.tag == ARRAY) {
0499:                            poolbuf.appendChar(pool.put(typeSig(c.type)));
0500:                        } else {
0501:                            poolbuf.appendChar(pool.put(names
0502:                                    .fromUtf(externalize(c.flatname))));
0503:                            enterInner(c);
0504:                        }
0505:                    } else if (value instanceof  NameAndType) {
0506:                        NameAndType nt = (NameAndType) value;
0507:                        poolbuf.appendByte(CONSTANT_NameandType);
0508:                        poolbuf.appendChar(pool.put(nt.name));
0509:                        poolbuf.appendChar(pool.put(typeSig(nt.type)));
0510:                    } else if (value instanceof  Integer) {
0511:                        poolbuf.appendByte(CONSTANT_Integer);
0512:                        poolbuf.appendInt(((Integer) value).intValue());
0513:                    } else if (value instanceof  Long) {
0514:                        poolbuf.appendByte(CONSTANT_Long);
0515:                        poolbuf.appendLong(((Long) value).longValue());
0516:                        i++;
0517:                    } else if (value instanceof  Float) {
0518:                        poolbuf.appendByte(CONSTANT_Float);
0519:                        poolbuf.appendFloat(((Float) value).floatValue());
0520:                    } else if (value instanceof  Double) {
0521:                        poolbuf.appendByte(CONSTANT_Double);
0522:                        poolbuf.appendDouble(((Double) value).doubleValue());
0523:                        i++;
0524:                    } else if (value instanceof  String) {
0525:                        poolbuf.appendByte(CONSTANT_String);
0526:                        poolbuf.appendChar(pool.put(names
0527:                                .fromString((String) value)));
0528:                    } else if (value instanceof  Type) {
0529:                        Type type = (Type) value;
0530:                        if (type.tag == CLASS)
0531:                            enterInner((ClassSymbol) type.tsym);
0532:                        poolbuf.appendByte(CONSTANT_Class);
0533:                        poolbuf.appendChar(pool.put(xClassName(type)));
0534:                    } else {
0535:                        assert false : "writePool " + value;
0536:                    }
0537:                    i++;
0538:                }
0539:                if (pool.pp > Pool.MAX_ENTRIES)
0540:                    throw new PoolOverflow();
0541:                putChar(poolbuf, poolCountIdx, pool.pp);
0542:            }
0543:
0544:            /** Given a field, return its name.
0545:             */
0546:            Name fieldName(Symbol sym) {
0547:                if (scramble && (sym.flags() & PRIVATE) != 0 || scrambleAll
0548:                        && (sym.flags() & (PROTECTED | PUBLIC)) == 0)
0549:                    return names.fromString("_$" + sym.name.index);
0550:                else
0551:                    return sym.name;
0552:            }
0553:
0554:            /** Given a symbol, return its name-and-type.
0555:             */
0556:            NameAndType nameType(Symbol sym) {
0557:                return new NameAndType(fieldName(sym), retrofit ? sym
0558:                        .erasure(types) : sym.externalType(types));
0559:                // if we retrofit, then the NameAndType has been read in as is
0560:                // and no change is necessary. If we compile normally, the
0561:                // NameAndType is generated from a symbol reference, and the
0562:                // adjustment of adding an additional this$n parameter needs to be made.
0563:            }
0564:
0565:            /******************************************************************
0566:             * Writing Attributes
0567:             ******************************************************************/
0568:
0569:            /** Write header for an attribute to data buffer and return
0570:             *  position past attribute length index.
0571:             */
0572:            int writeAttr(Name attrName) {
0573:                databuf.appendChar(pool.put(attrName));
0574:                databuf.appendInt(0);
0575:                return databuf.length;
0576:            }
0577:
0578:            /** Fill in attribute length.
0579:             */
0580:            void endAttr(int index) {
0581:                putInt(databuf, index - 4, databuf.length - index);
0582:            }
0583:
0584:            /** Leave space for attribute count and return index for
0585:             *  number of attributes field.
0586:             */
0587:            int beginAttrs() {
0588:                databuf.appendChar(0);
0589:                return databuf.length;
0590:            }
0591:
0592:            /** Fill in number of attributes.
0593:             */
0594:            void endAttrs(int index, int count) {
0595:                putChar(databuf, index - 2, count);
0596:            }
0597:
0598:            /** Write the EnclosingMethod attribute if needed.
0599:             *  Returns the number of attributes written (0 or 1).
0600:             */
0601:            int writeEnclosingMethodAttribute(ClassSymbol c) {
0602:                if (!target.hasEnclosingMethodAttribute()
0603:                        || c.owner.kind != MTH && // neither a local class
0604:                        c.name != names.empty) // nor anonymous
0605:                    return 0;
0606:
0607:                int alenIdx = writeAttr(names.EnclosingMethod);
0608:                ClassSymbol enclClass = c.owner.enclClass();
0609:                MethodSymbol enclMethod = (c.owner.type == null // local to init block
0610:                || c.owner.kind != MTH) // or member init
0611:                ? null
0612:                        : (MethodSymbol) c.owner;
0613:                databuf.appendChar(pool.put(enclClass));
0614:                databuf.appendChar(enclMethod == null ? 0 : pool
0615:                        .put(nameType(c.owner)));
0616:                endAttr(alenIdx);
0617:                return 1;
0618:            }
0619:
0620:            /** Write flag attributes; return number of attributes written.
0621:             */
0622:            int writeFlagAttrs(long flags) {
0623:                int acount = 0;
0624:                if ((flags & DEPRECATED) != 0) {
0625:                    int alenIdx = writeAttr(names.Deprecated);
0626:                    endAttr(alenIdx);
0627:                    acount++;
0628:                }
0629:                if ((flags & ENUM) != 0 && !target.useEnumFlag()) {
0630:                    int alenIdx = writeAttr(names.Enum);
0631:                    endAttr(alenIdx);
0632:                    acount++;
0633:                }
0634:                if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) {
0635:                    int alenIdx = writeAttr(names.Synthetic);
0636:                    endAttr(alenIdx);
0637:                    acount++;
0638:                }
0639:                if ((flags & BRIDGE) != 0 && !target.useBridgeFlag()) {
0640:                    int alenIdx = writeAttr(names.Bridge);
0641:                    endAttr(alenIdx);
0642:                    acount++;
0643:                }
0644:                if ((flags & VARARGS) != 0 && !target.useVarargsFlag()) {
0645:                    int alenIdx = writeAttr(names.Varargs);
0646:                    endAttr(alenIdx);
0647:                    acount++;
0648:                }
0649:                if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag()) {
0650:                    int alenIdx = writeAttr(names.Annotation);
0651:                    endAttr(alenIdx);
0652:                    acount++;
0653:                }
0654:                return acount;
0655:            }
0656:
0657:            /** Write member (field or method) attributes;
0658:             *  return number of attributes written.
0659:             */
0660:            int writeMemberAttrs(Symbol sym) {
0661:                int acount = writeFlagAttrs(sym.flags());
0662:                long flags = sym.flags();
0663:                if (source.allowGenerics()
0664:                        && (flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC
0665:                        && (flags & ANONCONSTR) == 0
0666:                        && (!types.isSameType(sym.type, sym.erasure(types)) || hasTypeVar(sym.type
0667:                                .getThrownTypes()))) {
0668:                    // note that a local class with captured variables
0669:                    // will get a signature attribute
0670:                    int alenIdx = writeAttr(names.Signature);
0671:                    databuf.appendChar(pool.put(typeSig(sym.type)));
0672:                    endAttr(alenIdx);
0673:                    acount++;
0674:                }
0675:                acount += writeJavaAnnotations(sym.getAnnotationMirrors());
0676:                return acount;
0677:            }
0678:
0679:            /** Write method parameter annotations;
0680:             *  return number of attributes written.
0681:             */
0682:            int writeParameterAttrs(MethodSymbol m) {
0683:                boolean hasVisible = false;
0684:                boolean hasInvisible = false;
0685:                if (m.params != null)
0686:                    for (VarSymbol s : m.params) {
0687:                        for (Attribute.Compound a : s.getAnnotationMirrors()) {
0688:                            switch (getRetention(a.type.tsym)) {
0689:                            case SOURCE:
0690:                                break;
0691:                            case CLASS:
0692:                                hasInvisible = true;
0693:                                break;
0694:                            case RUNTIME:
0695:                                hasVisible = true;
0696:                                break;
0697:                            default:
0698:                                ;// /* fail soft */ throw new AssertionError(vis);
0699:                            }
0700:                        }
0701:                    }
0702:
0703:                int attrCount = 0;
0704:                if (hasVisible) {
0705:                    int attrIndex = writeAttr(names.RuntimeVisibleParameterAnnotations);
0706:                    databuf.appendByte(m.params.length());
0707:                    for (VarSymbol s : m.params) {
0708:                        ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
0709:                        for (Attribute.Compound a : s.getAnnotationMirrors())
0710:                            if (getRetention(a.type.tsym) == RetentionPolicy.RUNTIME)
0711:                                buf.append(a);
0712:                        databuf.appendChar(buf.length());
0713:                        for (Attribute.Compound a : buf)
0714:                            writeCompoundAttribute(a);
0715:                    }
0716:                    endAttr(attrIndex);
0717:                    attrCount++;
0718:                }
0719:                if (hasInvisible) {
0720:                    int attrIndex = writeAttr(names.RuntimeInvisibleParameterAnnotations);
0721:                    databuf.appendByte(m.params.length());
0722:                    for (VarSymbol s : m.params) {
0723:                        ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
0724:                        for (Attribute.Compound a : s.getAnnotationMirrors())
0725:                            if (getRetention(a.type.tsym) == RetentionPolicy.CLASS)
0726:                                buf.append(a);
0727:                        databuf.appendChar(buf.length());
0728:                        for (Attribute.Compound a : buf)
0729:                            writeCompoundAttribute(a);
0730:                    }
0731:                    endAttr(attrIndex);
0732:                    attrCount++;
0733:                }
0734:                return attrCount;
0735:            }
0736:
0737:            /**********************************************************************
0738:             * Writing Java-language annotations (aka metadata, attributes)
0739:             **********************************************************************/
0740:
0741:            /** Write Java-language annotations; return number of JVM
0742:             *  attributes written (zero or one).
0743:             */
0744:            int writeJavaAnnotations(List<Attribute.Compound> attrs) {
0745:                if (attrs.isEmpty())
0746:                    return 0;
0747:                ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>();
0748:                ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>();
0749:                for (Attribute.Compound a : attrs) {
0750:                    switch (getRetention(a.type.tsym)) {
0751:                    case SOURCE:
0752:                        break;
0753:                    case CLASS:
0754:                        invisibles.append(a);
0755:                        break;
0756:                    case RUNTIME:
0757:                        visibles.append(a);
0758:                        break;
0759:                    default:
0760:                        ;// /* fail soft */ throw new AssertionError(vis);
0761:                    }
0762:                }
0763:
0764:                int attrCount = 0;
0765:                if (visibles.length() != 0) {
0766:                    int attrIndex = writeAttr(names.RuntimeVisibleAnnotations);
0767:                    databuf.appendChar(visibles.length());
0768:                    for (Attribute.Compound a : visibles)
0769:                        writeCompoundAttribute(a);
0770:                    endAttr(attrIndex);
0771:                    attrCount++;
0772:                }
0773:                if (invisibles.length() != 0) {
0774:                    int attrIndex = writeAttr(names.RuntimeInvisibleAnnotations);
0775:                    databuf.appendChar(invisibles.length());
0776:                    for (Attribute.Compound a : invisibles)
0777:                        writeCompoundAttribute(a);
0778:                    endAttr(attrIndex);
0779:                    attrCount++;
0780:                }
0781:                return attrCount;
0782:            }
0783:
0784:            /** A mirror of java.lang.annotation.RetentionPolicy. */
0785:            enum RetentionPolicy {
0786:                SOURCE, CLASS, RUNTIME
0787:            }
0788:
0789:            RetentionPolicy getRetention(TypeSymbol annotationType) {
0790:                RetentionPolicy vis = RetentionPolicy.CLASS; // the default
0791:                Attribute.Compound c = annotationType
0792:                        .attribute(syms.retentionType.tsym);
0793:                if (c != null) {
0794:                    Attribute value = c.member(names.value);
0795:                    if (value != null && value instanceof  Attribute.Enum) {
0796:                        Name levelName = ((Attribute.Enum) value).value.name;
0797:                        if (levelName == names.SOURCE)
0798:                            vis = RetentionPolicy.SOURCE;
0799:                        else if (levelName == names.CLASS)
0800:                            vis = RetentionPolicy.CLASS;
0801:                        else if (levelName == names.RUNTIME)
0802:                            vis = RetentionPolicy.RUNTIME;
0803:                        else
0804:                            ;// /* fail soft */ throw new AssertionError(levelName);
0805:                    }
0806:                }
0807:                return vis;
0808:            }
0809:
0810:            /** A visitor to write an attribute including its leading
0811:             *  single-character marker.
0812:             */
0813:            class AttributeWriter implements  Attribute.Visitor {
0814:                public void visitConstant(Attribute.Constant _value) {
0815:                    Object value = _value.value;
0816:                    switch (_value.type.tag) {
0817:                    case BYTE:
0818:                        databuf.appendByte('B');
0819:                        break;
0820:                    case CHAR:
0821:                        databuf.appendByte('C');
0822:                        break;
0823:                    case SHORT:
0824:                        databuf.appendByte('S');
0825:                        break;
0826:                    case INT:
0827:                        databuf.appendByte('I');
0828:                        break;
0829:                    case LONG:
0830:                        databuf.appendByte('J');
0831:                        break;
0832:                    case FLOAT:
0833:                        databuf.appendByte('F');
0834:                        break;
0835:                    case DOUBLE:
0836:                        databuf.appendByte('D');
0837:                        break;
0838:                    case BOOLEAN:
0839:                        databuf.appendByte('Z');
0840:                        break;
0841:                    case CLASS:
0842:                        assert value instanceof  String;
0843:                        databuf.appendByte('s');
0844:                        value = names.fromString(value.toString()); // CONSTANT_Utf8
0845:                        break;
0846:                    default:
0847:                        throw new AssertionError(_value.type);
0848:                    }
0849:                    databuf.appendChar(pool.put(value));
0850:                }
0851:
0852:                public void visitEnum(Attribute.Enum e) {
0853:                    databuf.appendByte('e');
0854:                    databuf.appendChar(pool.put(typeSig(e.value.type)));
0855:                    databuf.appendChar(pool.put(e.value.name));
0856:                }
0857:
0858:                public void visitClass(Attribute.Class clazz) {
0859:                    databuf.appendByte('c');
0860:                    databuf.appendChar(pool.put(typeSig(clazz.type)));
0861:                }
0862:
0863:                public void visitCompound(Attribute.Compound compound) {
0864:                    databuf.appendByte('@');
0865:                    writeCompoundAttribute(compound);
0866:                }
0867:
0868:                public void visitError(Attribute.Error x) {
0869:                    throw new AssertionError(x);
0870:                }
0871:
0872:                public void visitArray(Attribute.Array array) {
0873:                    databuf.appendByte('[');
0874:                    databuf.appendChar(array.values.length);
0875:                    for (Attribute a : array.values) {
0876:                        a.accept(this );
0877:                    }
0878:                }
0879:            }
0880:
0881:            AttributeWriter awriter = new AttributeWriter();
0882:
0883:            /** Write a compound attribute excluding the '@' marker. */
0884:            void writeCompoundAttribute(Attribute.Compound c) {
0885:                databuf.appendChar(pool.put(typeSig(c.type)));
0886:                databuf.appendChar(c.values.length());
0887:                for (Pair<Symbol.MethodSymbol, Attribute> p : c.values) {
0888:                    databuf.appendChar(pool.put(p.fst.name));
0889:                    p.snd.accept(awriter);
0890:                }
0891:            }
0892:
0893:            /**********************************************************************
0894:             * Writing Objects
0895:             **********************************************************************/
0896:
0897:            /** Enter an inner class into the `innerClasses' set/queue.
0898:             */
0899:            void enterInner(ClassSymbol c) {
0900:                assert !c.type.isCompound();
0901:                try {
0902:                    c.complete();
0903:                } catch (CompletionFailure ex) {
0904:                    System.err.println("error: " + c + ": " + ex.getMessage());
0905:                    throw ex;
0906:                }
0907:                if (c.type.tag != CLASS)
0908:                    return; // arrays
0909:                if (pool != null
0910:                        && // pool might be null if called from xClassName
0911:                        c.owner.kind != PCK
0912:                        && (innerClasses == null || !innerClasses.contains(c))) {
0913:                    //          log.errWriter.println("enter inner " + c);//DEBUG
0914:                    if (c.owner.kind == TYP)
0915:                        enterInner((ClassSymbol) c.owner);
0916:                    pool.put(c);
0917:                    pool.put(c.name);
0918:                    if (innerClasses == null) {
0919:                        innerClasses = new HashSet<ClassSymbol>();
0920:                        innerClassesQueue = new ListBuffer<ClassSymbol>();
0921:                        pool.put(names.InnerClasses);
0922:                    }
0923:                    innerClasses.add(c);
0924:                    innerClassesQueue.append(c);
0925:                }
0926:            }
0927:
0928:            /** Write "inner classes" attribute.
0929:             */
0930:            void writeInnerClasses() {
0931:                int alenIdx = writeAttr(names.InnerClasses);
0932:                databuf.appendChar(innerClassesQueue.length());
0933:                for (List<ClassSymbol> l = innerClassesQueue.toList(); l
0934:                        .nonEmpty(); l = l.tail) {
0935:                    ClassSymbol inner = l.head;
0936:                    char flags = (char) adjustFlags(inner.flags_field);
0937:                    if ((flags & INTERFACE) != 0)
0938:                        flags |= ABSTRACT; // Interfaces are always ABSTRACT
0939:                    if (inner.name.isEmpty())
0940:                        flags &= ~FINAL; // Anonymous class: unset FINAL flag
0941:                    if (dumpInnerClassModifiers) {
0942:                        log.errWriter.println("INNERCLASS  " + inner.name);
0943:                        log.errWriter.println("---" + flagNames(flags));
0944:                    }
0945:                    databuf.appendChar(pool.get(inner));
0946:                    databuf.appendChar(inner.owner.kind == TYP ? pool
0947:                            .get(inner.owner) : 0);
0948:                    databuf.appendChar(inner.name.len != 0 ? pool
0949:                            .get(inner.name) : 0);
0950:                    databuf.appendChar(flags);
0951:                }
0952:                endAttr(alenIdx);
0953:            }
0954:
0955:            /** Write field symbol, entering all references into constant pool.
0956:             */
0957:            void writeField(VarSymbol v) {
0958:                int flags = adjustFlags(v.flags());
0959:                databuf.appendChar(flags);
0960:                if (dumpFieldModifiers) {
0961:                    log.errWriter.println("FIELD  " + fieldName(v));
0962:                    log.errWriter.println("---" + flagNames(v.flags()));
0963:                }
0964:                databuf.appendChar(pool.put(fieldName(v)));
0965:                databuf.appendChar(pool.put(typeSig(v.erasure(types))));
0966:                int acountIdx = beginAttrs();
0967:                int acount = 0;
0968:                if (v.getConstValue() != null) {
0969:                    int alenIdx = writeAttr(names.ConstantValue);
0970:                    databuf.appendChar(pool.put(v.getConstValue()));
0971:                    endAttr(alenIdx);
0972:                    acount++;
0973:                }
0974:                acount += writeMemberAttrs(v);
0975:                endAttrs(acountIdx, acount);
0976:            }
0977:
0978:            /** Write method symbol, entering all references into constant pool.
0979:             */
0980:            void writeMethod(MethodSymbol m) {
0981:                int flags = adjustFlags(m.flags());
0982:                databuf.appendChar(flags);
0983:                if (dumpMethodModifiers) {
0984:                    log.errWriter.println("METHOD  " + fieldName(m));
0985:                    log.errWriter.println("---" + flagNames(m.flags()));
0986:                }
0987:                databuf.appendChar(pool.put(fieldName(m)));
0988:                databuf.appendChar(pool.put(typeSig(m.externalType(types))));
0989:                int acountIdx = beginAttrs();
0990:                int acount = 0;
0991:                if (m.code != null) {
0992:                    int alenIdx = writeAttr(names.Code);
0993:                    writeCode(m.code);
0994:                    m.code = null; // to conserve space
0995:                    endAttr(alenIdx);
0996:                    acount++;
0997:                }
0998:                List<Type> thrown = m.erasure(types).getThrownTypes();
0999:                if (thrown.nonEmpty()) {
1000:                    int alenIdx = writeAttr(names.Exceptions);
1001:                    databuf.appendChar(thrown.length());
1002:                    for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1003:                        databuf.appendChar(pool.put(l.head.tsym));
1004:                    endAttr(alenIdx);
1005:                    acount++;
1006:                }
1007:                if (m.defaultValue != null) {
1008:                    int alenIdx = writeAttr(names.AnnotationDefault);
1009:                    m.defaultValue.accept(awriter);
1010:                    endAttr(alenIdx);
1011:                    acount++;
1012:                }
1013:                acount += writeMemberAttrs(m);
1014:                acount += writeParameterAttrs(m);
1015:                endAttrs(acountIdx, acount);
1016:            }
1017:
1018:            /** Write code attribute of method.
1019:             */
1020:            void writeCode(Code code) {
1021:                databuf.appendChar(code.max_stack);
1022:                databuf.appendChar(code.max_locals);
1023:                databuf.appendInt(code.cp);
1024:                databuf.appendBytes(code.code, 0, code.cp);
1025:                databuf.appendChar(code.catchInfo.length());
1026:                for (List<char[]> l = code.catchInfo.toList(); l.nonEmpty(); l = l.tail) {
1027:                    for (int i = 0; i < l.head.length; i++)
1028:                        databuf.appendChar(l.head[i]);
1029:                }
1030:                int acountIdx = beginAttrs();
1031:                int acount = 0;
1032:
1033:                if (code.lineInfo.nonEmpty()) {
1034:                    int alenIdx = writeAttr(names.LineNumberTable);
1035:                    databuf.appendChar(code.lineInfo.length());
1036:                    for (List<char[]> l = code.lineInfo.reverse(); l.nonEmpty(); l = l.tail)
1037:                        for (int i = 0; i < l.head.length; i++)
1038:                            databuf.appendChar(l.head[i]);
1039:                    endAttr(alenIdx);
1040:                    acount++;
1041:                }
1042:
1043:                if (genCrt && (code.crt != null)) {
1044:                    CRTable crt = code.crt;
1045:                    int alenIdx = writeAttr(names.CharacterRangeTable);
1046:                    int crtIdx = beginAttrs();
1047:                    int crtEntries = crt.writeCRT(databuf, code.lineMap, log);
1048:                    endAttrs(crtIdx, crtEntries);
1049:                    endAttr(alenIdx);
1050:                    acount++;
1051:                }
1052:
1053:                // counter for number of generic local variables
1054:                int nGenericVars = 0;
1055:
1056:                if (code.varBufferSize > 0) {
1057:                    int alenIdx = writeAttr(names.LocalVariableTable);
1058:                    databuf.appendChar(code.varBufferSize);
1059:
1060:                    for (int i = 0; i < code.varBufferSize; i++) {
1061:                        Code.LocalVar var = code.varBuffer[i];
1062:
1063:                        // write variable info
1064:                        assert var.start_pc >= 0;
1065:                        assert var.start_pc <= code.cp;
1066:                        databuf.appendChar(var.start_pc);
1067:                        assert var.length >= 0;
1068:                        assert (var.start_pc + var.length) <= code.cp;
1069:                        databuf.appendChar(var.length);
1070:                        VarSymbol sym = var.sym;
1071:                        databuf.appendChar(pool.put(sym.name));
1072:                        Type vartype = sym.erasure(types);
1073:                        if (!types.isSameType(sym.type, vartype))
1074:                            nGenericVars++;
1075:                        databuf.appendChar(pool.put(typeSig(vartype)));
1076:                        databuf.appendChar(var.reg);
1077:                    }
1078:                    endAttr(alenIdx);
1079:                    acount++;
1080:                }
1081:
1082:                if (nGenericVars > 0) {
1083:                    int alenIdx = writeAttr(names.LocalVariableTypeTable);
1084:                    databuf.appendChar(nGenericVars);
1085:                    int count = 0;
1086:
1087:                    for (int i = 0; i < code.varBufferSize; i++) {
1088:                        Code.LocalVar var = code.varBuffer[i];
1089:                        VarSymbol sym = var.sym;
1090:                        if (types.isSameType(sym.type, sym.erasure(types)))
1091:                            continue;
1092:                        count++;
1093:                        // write variable info
1094:                        databuf.appendChar(var.start_pc);
1095:                        databuf.appendChar(var.length);
1096:                        databuf.appendChar(pool.put(sym.name));
1097:                        databuf.appendChar(pool.put(typeSig(sym.type)));
1098:                        databuf.appendChar(var.reg);
1099:                    }
1100:                    assert count == nGenericVars;
1101:                    endAttr(alenIdx);
1102:                    acount++;
1103:                }
1104:
1105:                if (code.stackMapBufferSize > 0) {
1106:                    if (debugstackmap)
1107:                        System.out.println("Stack map for " + code.meth);
1108:                    int alenIdx = writeAttr(code.stackMap
1109:                            .getAttributeName(names));
1110:                    writeStackMap(code);
1111:                    endAttr(alenIdx);
1112:                    acount++;
1113:                }
1114:                endAttrs(acountIdx, acount);
1115:            }
1116:
1117:            void writeStackMap(Code code) {
1118:                int nframes = code.stackMapBufferSize;
1119:                if (debugstackmap)
1120:                    System.out.println(" nframes = " + nframes);
1121:                databuf.appendChar(nframes);
1122:
1123:                switch (code.stackMap) {
1124:                case CLDC:
1125:                    for (int i = 0; i < nframes; i++) {
1126:                        if (debugstackmap)
1127:                            System.out.print("  " + i + ":");
1128:                        Code.StackMapFrame frame = code.stackMapBuffer[i];
1129:
1130:                        // output PC
1131:                        if (debugstackmap)
1132:                            System.out.print(" pc=" + frame.pc);
1133:                        databuf.appendChar(frame.pc);
1134:
1135:                        // output locals
1136:                        int localCount = 0;
1137:                        for (int j = 0; j < frame.locals.length; j += (target
1138:                                .generateEmptyAfterBig() ? 1 : Code
1139:                                .width(frame.locals[j]))) {
1140:                            localCount++;
1141:                        }
1142:                        if (debugstackmap)
1143:                            System.out.print(" nlocals=" + localCount);
1144:                        databuf.appendChar(localCount);
1145:                        for (int j = 0; j < frame.locals.length; j += (target
1146:                                .generateEmptyAfterBig() ? 1 : Code
1147:                                .width(frame.locals[j]))) {
1148:                            if (debugstackmap)
1149:                                System.out.print(" local[" + j + "]=");
1150:                            writeStackMapType(frame.locals[j]);
1151:                        }
1152:
1153:                        // output stack
1154:                        int stackCount = 0;
1155:                        for (int j = 0; j < frame.stack.length; j += (target
1156:                                .generateEmptyAfterBig() ? 1 : Code
1157:                                .width(frame.stack[j]))) {
1158:                            stackCount++;
1159:                        }
1160:                        if (debugstackmap)
1161:                            System.out.print(" nstack=" + stackCount);
1162:                        databuf.appendChar(stackCount);
1163:                        for (int j = 0; j < frame.stack.length; j += (target
1164:                                .generateEmptyAfterBig() ? 1 : Code
1165:                                .width(frame.stack[j]))) {
1166:                            if (debugstackmap)
1167:                                System.out.print(" stack[" + j + "]=");
1168:                            writeStackMapType(frame.stack[j]);
1169:                        }
1170:                        if (debugstackmap)
1171:                            System.out.println();
1172:                    }
1173:                    break;
1174:                case JSR202: {
1175:                    assert code.stackMapBuffer == null;
1176:                    for (int i = 0; i < nframes; i++) {
1177:                        if (debugstackmap)
1178:                            System.out.print("  " + i + ":");
1179:                        StackMapTableFrame frame = code.stackMapTableBuffer[i];
1180:                        frame.write(this );
1181:                        if (debugstackmap)
1182:                            System.out.println();
1183:                    }
1184:                    break;
1185:                }
1186:                default:
1187:                    throw new AssertionError("Unexpected stackmap format value");
1188:                }
1189:            }
1190:
1191:            //where
1192:            void writeStackMapType(Type t) {
1193:                if (t == null) {
1194:                    if (debugstackmap)
1195:                        System.out.print("empty");
1196:                    databuf.appendByte(0);
1197:                } else
1198:                    switch (t.tag) {
1199:                    case BYTE:
1200:                    case CHAR:
1201:                    case SHORT:
1202:                    case INT:
1203:                    case BOOLEAN:
1204:                        if (debugstackmap)
1205:                            System.out.print("int");
1206:                        databuf.appendByte(1);
1207:                        break;
1208:                    case FLOAT:
1209:                        if (debugstackmap)
1210:                            System.out.print("float");
1211:                        databuf.appendByte(2);
1212:                        break;
1213:                    case DOUBLE:
1214:                        if (debugstackmap)
1215:                            System.out.print("double");
1216:                        databuf.appendByte(3);
1217:                        break;
1218:                    case LONG:
1219:                        if (debugstackmap)
1220:                            System.out.print("long");
1221:                        databuf.appendByte(4);
1222:                        break;
1223:                    case BOT: // null
1224:                        if (debugstackmap)
1225:                            System.out.print("null");
1226:                        databuf.appendByte(5);
1227:                        break;
1228:                    case CLASS:
1229:                    case ARRAY:
1230:                        if (debugstackmap)
1231:                            System.out.print("object(" + t + ")");
1232:                        databuf.appendByte(7);
1233:                        databuf.appendChar(pool.put(t));
1234:                        break;
1235:                    case TYPEVAR:
1236:                        if (debugstackmap)
1237:                            System.out.print("object(" + types.erasure(t).tsym
1238:                                    + ")");
1239:                        databuf.appendByte(7);
1240:                        databuf.appendChar(pool.put(types.erasure(t).tsym));
1241:                        break;
1242:                    case UNINITIALIZED_THIS:
1243:                        if (debugstackmap)
1244:                            System.out.print("uninit_this");
1245:                        databuf.appendByte(6);
1246:                        break;
1247:                    case UNINITIALIZED_OBJECT: {
1248:                        UninitializedType uninitType = (UninitializedType) t;
1249:                        databuf.appendByte(8);
1250:                        if (debugstackmap)
1251:                            System.out.print("uninit_object@"
1252:                                    + uninitType.offset);
1253:                        databuf.appendChar(uninitType.offset);
1254:                    }
1255:                        break;
1256:                    default:
1257:                        throw new AssertionError();
1258:                    }
1259:            }
1260:
1261:            /** An entry in the JSR202 StackMapTable */
1262:            abstract static class StackMapTableFrame {
1263:                abstract int getFrameType();
1264:
1265:                void write(ClassWriter writer) {
1266:                    int frameType = getFrameType();
1267:                    writer.databuf.appendByte(frameType);
1268:                    if (writer.debugstackmap)
1269:                        System.out.print(" frame_type=" + frameType);
1270:                }
1271:
1272:                static class SameFrame extends StackMapTableFrame {
1273:                    final int offsetDelta;
1274:
1275:                    SameFrame(int offsetDelta) {
1276:                        this .offsetDelta = offsetDelta;
1277:                    }
1278:
1279:                    int getFrameType() {
1280:                        return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta
1281:                                : SAME_FRAME_EXTENDED;
1282:                    }
1283:
1284:                    @Override
1285:                    void write(ClassWriter writer) {
1286:                        super .write(writer);
1287:                        if (getFrameType() == SAME_FRAME_EXTENDED) {
1288:                            writer.databuf.appendChar(offsetDelta);
1289:                            if (writer.debugstackmap) {
1290:                                System.out
1291:                                        .print(" offset_delta=" + offsetDelta);
1292:                            }
1293:                        }
1294:                    }
1295:                }
1296:
1297:                static class SameLocals1StackItemFrame extends
1298:                        StackMapTableFrame {
1299:                    final int offsetDelta;
1300:                    final Type stack;
1301:
1302:                    SameLocals1StackItemFrame(int offsetDelta, Type stack) {
1303:                        this .offsetDelta = offsetDelta;
1304:                        this .stack = stack;
1305:                    }
1306:
1307:                    int getFrameType() {
1308:                        return (offsetDelta < SAME_FRAME_SIZE) ? (SAME_FRAME_SIZE + offsetDelta)
1309:                                : SAME_LOCALS_1_STACK_ITEM_EXTENDED;
1310:                    }
1311:
1312:                    @Override
1313:                    void write(ClassWriter writer) {
1314:                        super .write(writer);
1315:                        if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
1316:                            writer.databuf.appendChar(offsetDelta);
1317:                            if (writer.debugstackmap) {
1318:                                System.out
1319:                                        .print(" offset_delta=" + offsetDelta);
1320:                            }
1321:                        }
1322:                        if (writer.debugstackmap) {
1323:                            System.out.print(" stack[" + 0 + "]=");
1324:                        }
1325:                        writer.writeStackMapType(stack);
1326:                    }
1327:                }
1328:
1329:                static class ChopFrame extends StackMapTableFrame {
1330:                    final int frameType;
1331:                    final int offsetDelta;
1332:
1333:                    ChopFrame(int frameType, int offsetDelta) {
1334:                        this .frameType = frameType;
1335:                        this .offsetDelta = offsetDelta;
1336:                    }
1337:
1338:                    int getFrameType() {
1339:                        return frameType;
1340:                    }
1341:
1342:                    @Override
1343:                    void write(ClassWriter writer) {
1344:                        super .write(writer);
1345:                        writer.databuf.appendChar(offsetDelta);
1346:                        if (writer.debugstackmap) {
1347:                            System.out.print(" offset_delta=" + offsetDelta);
1348:                        }
1349:                    }
1350:                }
1351:
1352:                static class AppendFrame extends StackMapTableFrame {
1353:                    final int frameType;
1354:                    final int offsetDelta;
1355:                    final Type[] locals;
1356:
1357:                    AppendFrame(int frameType, int offsetDelta, Type[] locals) {
1358:                        this .frameType = frameType;
1359:                        this .offsetDelta = offsetDelta;
1360:                        this .locals = locals;
1361:                    }
1362:
1363:                    int getFrameType() {
1364:                        return frameType;
1365:                    }
1366:
1367:                    @Override
1368:                    void write(ClassWriter writer) {
1369:                        super .write(writer);
1370:                        writer.databuf.appendChar(offsetDelta);
1371:                        if (writer.debugstackmap) {
1372:                            System.out.print(" offset_delta=" + offsetDelta);
1373:                        }
1374:                        for (int i = 0; i < locals.length; i++) {
1375:                            if (writer.debugstackmap)
1376:                                System.out.print(" locals[" + i + "]=");
1377:                            writer.writeStackMapType(locals[i]);
1378:                        }
1379:                    }
1380:                }
1381:
1382:                static class FullFrame extends StackMapTableFrame {
1383:                    final int offsetDelta;
1384:                    final Type[] locals;
1385:                    final Type[] stack;
1386:
1387:                    FullFrame(int offsetDelta, Type[] locals, Type[] stack) {
1388:                        this .offsetDelta = offsetDelta;
1389:                        this .locals = locals;
1390:                        this .stack = stack;
1391:                    }
1392:
1393:                    int getFrameType() {
1394:                        return FULL_FRAME;
1395:                    }
1396:
1397:                    @Override
1398:                    void write(ClassWriter writer) {
1399:                        super .write(writer);
1400:                        writer.databuf.appendChar(offsetDelta);
1401:                        writer.databuf.appendChar(locals.length);
1402:                        if (writer.debugstackmap) {
1403:                            System.out.print(" offset_delta=" + offsetDelta);
1404:                            System.out.print(" nlocals=" + locals.length);
1405:                        }
1406:                        for (int i = 0; i < locals.length; i++) {
1407:                            if (writer.debugstackmap)
1408:                                System.out.print(" locals[" + i + "]=");
1409:                            writer.writeStackMapType(locals[i]);
1410:                        }
1411:
1412:                        writer.databuf.appendChar(stack.length);
1413:                        if (writer.debugstackmap) {
1414:                            System.out.print(" nstack=" + stack.length);
1415:                        }
1416:                        for (int i = 0; i < stack.length; i++) {
1417:                            if (writer.debugstackmap)
1418:                                System.out.print(" stack[" + i + "]=");
1419:                            writer.writeStackMapType(stack[i]);
1420:                        }
1421:                    }
1422:                }
1423:
1424:                /** Compare this frame with the previous frame and produce
1425:                 *  an entry of compressed stack map frame. */
1426:                static StackMapTableFrame getInstance(
1427:                        Code.StackMapFrame this _frame, int prev_pc,
1428:                        Type[] prev_locals, Types types) {
1429:                    Type[] locals = this _frame.locals;
1430:                    Type[] stack = this _frame.stack;
1431:                    int offset_delta = this _frame.pc - prev_pc - 1;
1432:                    if (stack.length == 1) {
1433:                        if (locals.length == prev_locals.length
1434:                                && compare(prev_locals, locals, types) == 0) {
1435:                            return new SameLocals1StackItemFrame(offset_delta,
1436:                                    stack[0]);
1437:                        }
1438:                    } else if (stack.length == 0) {
1439:                        int diff_length = compare(prev_locals, locals, types);
1440:                        if (diff_length == 0) {
1441:                            return new SameFrame(offset_delta);
1442:                        } else if (-MAX_LOCAL_LENGTH_DIFF < diff_length
1443:                                && diff_length < 0) {
1444:                            // APPEND
1445:                            Type[] local_diff = new Type[-diff_length];
1446:                            for (int i = prev_locals.length, j = 0; i < locals.length; i++, j++) {
1447:                                local_diff[j] = locals[i];
1448:                            }
1449:                            return new AppendFrame(SAME_FRAME_EXTENDED
1450:                                    - diff_length, offset_delta, local_diff);
1451:                        } else if (0 < diff_length
1452:                                && diff_length < MAX_LOCAL_LENGTH_DIFF) {
1453:                            // CHOP 
1454:                            return new ChopFrame(SAME_FRAME_EXTENDED
1455:                                    - diff_length, offset_delta);
1456:                        }
1457:                    }
1458:                    // FULL_FRAME
1459:                    return new FullFrame(offset_delta, locals, stack);
1460:                }
1461:
1462:                static boolean isInt(Type t) {
1463:                    return (t.tag < TypeTags.INT || t.tag == TypeTags.BOOLEAN);
1464:                }
1465:
1466:                static boolean isSameType(Type t1, Type t2, Types types) {
1467:                    if (t1 == null) {
1468:                        return t2 == null;
1469:                    }
1470:                    if (t2 == null) {
1471:                        return false;
1472:                    }
1473:
1474:                    if (isInt(t1) && isInt(t2)) {
1475:                        return true;
1476:                    }
1477:
1478:                    if (t1.tag == UNINITIALIZED_THIS) {
1479:                        return t2.tag == UNINITIALIZED_THIS;
1480:                    } else if (t1.tag == UNINITIALIZED_OBJECT) {
1481:                        if (t2.tag == UNINITIALIZED_OBJECT) {
1482:                            return ((UninitializedType) t1).offset == ((UninitializedType) t2).offset;
1483:                        } else {
1484:                            return false;
1485:                        }
1486:                    } else if (t2.tag == UNINITIALIZED_THIS
1487:                            || t2.tag == UNINITIALIZED_OBJECT) {
1488:                        return false;
1489:                    }
1490:
1491:                    return types.isSameType(t1, t2);
1492:                }
1493:
1494:                static int compare(Type[] arr1, Type[] arr2, Types types) {
1495:                    int diff_length = arr1.length - arr2.length;
1496:                    if (diff_length > MAX_LOCAL_LENGTH_DIFF
1497:                            || diff_length < -MAX_LOCAL_LENGTH_DIFF) {
1498:                        return Integer.MAX_VALUE;
1499:                    }
1500:                    int len = (diff_length > 0) ? arr2.length : arr1.length;
1501:                    for (int i = 0; i < len; i++) {
1502:                        if (!isSameType(arr1[i], arr2[i], types)) {
1503:                            return Integer.MAX_VALUE;
1504:                        }
1505:                    }
1506:                    return diff_length;
1507:                }
1508:            }
1509:
1510:            void writeFields(Scope.Entry e) {
1511:                // process them in reverse sibling order;
1512:                // i.e., process them in declaration order.
1513:                List<VarSymbol> vars = List.nil();
1514:                for (Scope.Entry i = e; i != null; i = i.sibling) {
1515:                    if (i.sym.kind == VAR)
1516:                        vars = vars.prepend((VarSymbol) i.sym);
1517:                }
1518:                while (vars.nonEmpty()) {
1519:                    writeField(vars.head);
1520:                    vars = vars.tail;
1521:                }
1522:            }
1523:
1524:            void writeMethods(Scope.Entry e) {
1525:                List<MethodSymbol> methods = List.nil();
1526:                for (Scope.Entry i = e; i != null; i = i.sibling) {
1527:                    if (i.sym.kind == MTH
1528:                            && (i.sym.flags() & HYPOTHETICAL) == 0)
1529:                        methods = methods.prepend((MethodSymbol) i.sym);
1530:                }
1531:                while (methods.nonEmpty()) {
1532:                    writeMethod(methods.head);
1533:                    methods = methods.tail;
1534:                }
1535:            }
1536:
1537:            /** Emit a class file for a given class.
1538:             *  @param c      The class from which a class file is generated.
1539:             */
1540:            public JavaFileObject writeClass(ClassSymbol c) throws IOException,
1541:                    PoolOverflow, StringOverflow {
1542:                JavaFileObject outFile = fileManager.getJavaFileForOutput(
1543:                        CLASS_OUTPUT, c.flatname.toString(),
1544:                        JavaFileObject.Kind.CLASS, c.sourcefile);
1545:                OutputStream out = outFile.openOutputStream();
1546:                try {
1547:                    writeClassFile(out, c);
1548:                    if (verbose)
1549:                        log.errWriter.println(log.getLocalizedString(
1550:                                "verbose.wrote.file", outFile));
1551:                    out.close();
1552:                    out = null;
1553:                } finally {
1554:                    if (out != null) {
1555:                        // if we are propogating an exception, delete the file
1556:                        out.close();
1557:                        outFile.delete();
1558:                        outFile = null;
1559:                    }
1560:                }
1561:                return outFile; // may be null if write failed
1562:            }
1563:
1564:            /** Write class `c' to outstream `out'.
1565:             */
1566:            public void writeClassFile(OutputStream out, ClassSymbol c)
1567:                    throws IOException, PoolOverflow, StringOverflow {
1568:                assert (c.flags() & COMPOUND) == 0;
1569:                databuf.reset();
1570:                poolbuf.reset();
1571:                sigbuf.reset();
1572:                pool = c.pool;
1573:                innerClasses = null;
1574:                innerClassesQueue = null;
1575:
1576:                Type super type = types.super type(c.type);
1577:                List<Type> interfaces = types.interfaces(c.type);
1578:                List<Type> typarams = c.type.getTypeArguments();
1579:
1580:                int flags = adjustFlags(c.flags());
1581:                if ((flags & PROTECTED) != 0)
1582:                    flags |= PUBLIC;
1583:                flags = flags & ClassFlags & ~STRICTFP;
1584:                if ((flags & INTERFACE) == 0)
1585:                    flags |= ACC_SUPER;
1586:                if (c.isInner() && c.name.isEmpty())
1587:                    flags &= ~FINAL;
1588:                if (dumpClassModifiers) {
1589:                    log.errWriter.println();
1590:                    log.errWriter.println("CLASSFILE  " + c.getQualifiedName());
1591:                    log.errWriter.println("---" + flagNames(flags));
1592:                }
1593:                databuf.appendChar(flags);
1594:
1595:                databuf.appendChar(pool.put(c));
1596:                databuf.appendChar(super type.tag == CLASS ? pool
1597:                        .put(super type.tsym) : 0);
1598:                databuf.appendChar(interfaces.length());
1599:                for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1600:                    databuf.appendChar(pool.put(l.head.tsym));
1601:                int fieldsCount = 0;
1602:                int methodsCount = 0;
1603:                for (Scope.Entry e = c.members().elems; e != null; e = e.sibling) {
1604:                    switch (e.sym.kind) {
1605:                    case VAR:
1606:                        fieldsCount++;
1607:                        break;
1608:                    case MTH:
1609:                        if ((e.sym.flags() & HYPOTHETICAL) == 0)
1610:                            methodsCount++;
1611:                        break;
1612:                    case TYP:
1613:                        enterInner((ClassSymbol) e.sym);
1614:                        break;
1615:                    default:
1616:                        assert false;
1617:                    }
1618:                }
1619:                databuf.appendChar(fieldsCount);
1620:                writeFields(c.members().elems);
1621:                databuf.appendChar(methodsCount);
1622:                writeMethods(c.members().elems);
1623:
1624:                int acountIdx = beginAttrs();
1625:                int acount = 0;
1626:
1627:                boolean sigReq = typarams.length() != 0
1628:                        || super type.getTypeArguments().length() != 0;
1629:                for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1630:                    sigReq = l.head.getTypeArguments().length() != 0;
1631:                if (sigReq) {
1632:                    assert source.allowGenerics();
1633:                    int alenIdx = writeAttr(names.Signature);
1634:                    if (typarams.length() != 0)
1635:                        assembleParamsSig(typarams);
1636:                    assembleSig(super type);
1637:                    for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1638:                        assembleSig(l.head);
1639:                    databuf.appendChar(pool.put(sigbuf.toName(names)));
1640:                    sigbuf.reset();
1641:                    endAttr(alenIdx);
1642:                    acount++;
1643:                }
1644:
1645:                if (c.sourcefile != null && emitSourceFile) {
1646:                    int alenIdx = writeAttr(names.SourceFile);
1647:                    // WHM 6/29/1999: Strip file path prefix.  We do it here at
1648:                    // the last possible moment because the sourcefile may be used
1649:                    // elsewhere in error diagnostics. Fixes 4241573.
1650:                    //databuf.appendChar(c.pool.put(c.sourcefile));
1651:                    String filename = c.sourcefile.toString();
1652:                    int sepIdx = filename.lastIndexOf(File.separatorChar);
1653:                    // Allow '/' as separator on all platforms, e.g., on Win32.
1654:                    int slashIdx = filename.lastIndexOf('/');
1655:                    if (slashIdx > sepIdx)
1656:                        sepIdx = slashIdx;
1657:                    if (sepIdx >= 0)
1658:                        filename = filename.substring(sepIdx + 1);
1659:                    databuf.appendChar(c.pool.put(names.fromString(filename)));
1660:                    endAttr(alenIdx);
1661:                    acount++;
1662:                }
1663:
1664:                if (genCrt) {
1665:                    // Append SourceID attribute
1666:                    int alenIdx = writeAttr(names.SourceID);
1667:                    databuf.appendChar(c.pool.put(names.fromString(Long
1668:                            .toString(getLastModified(c.sourcefile)))));
1669:                    endAttr(alenIdx);
1670:                    acount++;
1671:                    // Append CompilationID attribute
1672:                    alenIdx = writeAttr(names.CompilationID);
1673:                    databuf.appendChar(c.pool.put(names.fromString(Long
1674:                            .toString(System.currentTimeMillis()))));
1675:                    endAttr(alenIdx);
1676:                    acount++;
1677:                }
1678:
1679:                acount += writeFlagAttrs(c.flags());
1680:                acount += writeJavaAnnotations(c.getAnnotationMirrors());
1681:                acount += writeEnclosingMethodAttribute(c);
1682:
1683:                poolbuf.appendInt(JAVA_MAGIC);
1684:                poolbuf.appendChar(target.minorVersion);
1685:                poolbuf.appendChar(target.majorVersion);
1686:
1687:                writePool(c.pool);
1688:
1689:                if (innerClasses != null) {
1690:                    writeInnerClasses();
1691:                    acount++;
1692:                }
1693:                endAttrs(acountIdx, acount);
1694:
1695:                poolbuf.appendBytes(databuf.elems, 0, databuf.length);
1696:                out.write(poolbuf.elems, 0, poolbuf.length);
1697:
1698:                pool = c.pool = null; // to conserve space
1699:            }
1700:
1701:            int adjustFlags(final long flags) {
1702:                int result = (int) flags;
1703:                if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag())
1704:                    result &= ~SYNTHETIC;
1705:                if ((flags & ENUM) != 0 && !target.useEnumFlag())
1706:                    result &= ~ENUM;
1707:                if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag())
1708:                    result &= ~ANNOTATION;
1709:
1710:                if ((flags & BRIDGE) != 0 && target.useBridgeFlag())
1711:                    result |= ACC_BRIDGE;
1712:                if ((flags & VARARGS) != 0 && target.useVarargsFlag())
1713:                    result |= ACC_VARARGS;
1714:                return result;
1715:            }
1716:
1717:            long getLastModified(FileObject filename) {
1718:                long mod = 0;
1719:                try {
1720:                    mod = filename.getLastModified();
1721:                } catch (SecurityException e) {
1722:                    throw new AssertionError(
1723:                            "CRT: couldn't get source file modification date: "
1724:                                    + e.getMessage());
1725:                }
1726:                return mod;
1727:            }
1728:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.