Source Code Cross Referenced for ClassFileWriter.java in  » Scripting » rhino » org » mozilla » classfile » 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 » Scripting » rhino » org.mozilla.classfile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-1999
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Roger Lawrence
0026:         *
0027:         * Alternatively, the contents of this file may be used under the terms of
0028:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0029:         * case the provisions of the GPL are applicable instead of those above. If
0030:         * you wish to allow use of your version of this file only under the terms of
0031:         * the GPL and not to allow others to use your version of this file under the
0032:         * MPL, indicate your decision by deleting the provisions above and replacing
0033:         * them with the notice and other provisions required by the GPL. If you do
0034:         * not delete the provisions above, a recipient may use your version of this
0035:         * file under either the MPL or the GPL.
0036:         *
0037:         * ***** END LICENSE BLOCK ***** */
0038:
0039:        package org.mozilla.classfile;
0040:
0041:        import org.mozilla.javascript.ObjToIntMap;
0042:        import org.mozilla.javascript.ObjArray;
0043:        import org.mozilla.javascript.UintMap;
0044:
0045:        import java.io.*;
0046:
0047:        /**
0048:         * ClassFileWriter
0049:         *
0050:         * A ClassFileWriter is used to write a Java class file. Methods are
0051:         * provided to create fields and methods, and within methods to write
0052:         * Java bytecodes.
0053:         *
0054:         * @author Roger Lawrence
0055:         */
0056:        public class ClassFileWriter {
0057:
0058:            /**
0059:             * Thrown for cases where the error in generating the class file is
0060:             * due to a program size constraints rather than a likely bug in the
0061:             * compiler.
0062:             */
0063:            public static class ClassFileFormatException extends
0064:                    RuntimeException {
0065:                ClassFileFormatException(String message) {
0066:                    super (message);
0067:                }
0068:            }
0069:
0070:            /**
0071:             * Construct a ClassFileWriter for a class.
0072:             *
0073:             * @param className the name of the class to write, including
0074:             *        full package qualification.
0075:             * @param superClassName the name of the superclass of the class
0076:             *        to write, including full package qualification.
0077:             * @param sourceFileName the name of the source file to use for
0078:             *        producing debug information, or null if debug information
0079:             *        is not desired
0080:             */
0081:            public ClassFileWriter(String className, String super ClassName,
0082:                    String sourceFileName) {
0083:                generatedClassName = className;
0084:                itsConstantPool = new ConstantPool(this );
0085:                itsThisClassIndex = itsConstantPool.addClass(className);
0086:                itsSuperClassIndex = itsConstantPool.addClass(super ClassName);
0087:                if (sourceFileName != null)
0088:                    itsSourceFileNameIndex = itsConstantPool
0089:                            .addUtf8(sourceFileName);
0090:                itsFlags = ACC_PUBLIC;
0091:            }
0092:
0093:            public final String getClassName() {
0094:                return generatedClassName;
0095:            }
0096:
0097:            /**
0098:             * Add an interface implemented by this class.
0099:             *
0100:             * This method may be called multiple times for classes that
0101:             * implement multiple interfaces.
0102:             *
0103:             * @param interfaceName a name of an interface implemented
0104:             *        by the class being written, including full package
0105:             *        qualification.
0106:             */
0107:            public void addInterface(String interfaceName) {
0108:                short interfaceIndex = itsConstantPool.addClass(interfaceName);
0109:                itsInterfaces.add(new Short(interfaceIndex));
0110:            }
0111:
0112:            public static final short ACC_PUBLIC = 0x0001,
0113:                    ACC_PRIVATE = 0x0002, ACC_PROTECTED = 0x0004,
0114:                    ACC_STATIC = 0x0008, ACC_FINAL = 0x0010,
0115:                    ACC_SYNCHRONIZED = 0x0020, ACC_VOLATILE = 0x0040,
0116:                    ACC_TRANSIENT = 0x0080, ACC_NATIVE = 0x0100,
0117:                    ACC_ABSTRACT = 0x0400;
0118:
0119:            /**
0120:             * Set the class's flags.
0121:             *
0122:             * Flags must be a set of the following flags, bitwise or'd
0123:             * together:
0124:             *      ACC_PUBLIC
0125:             *      ACC_PRIVATE
0126:             *      ACC_PROTECTED
0127:             *      ACC_FINAL
0128:             *      ACC_ABSTRACT
0129:             * TODO: check that this is the appropriate set
0130:             * @param flags the set of class flags to set
0131:             */
0132:            public void setFlags(short flags) {
0133:                itsFlags = flags;
0134:            }
0135:
0136:            static String getSlashedForm(String name) {
0137:                return name.replace('.', '/');
0138:            }
0139:
0140:            /**
0141:             * Convert Java class name in dot notation into
0142:             * "Lname-with-dots-replaced-by-slashes;" form suitable for use as
0143:             * JVM type signatures.
0144:             */
0145:            public static String classNameToSignature(String name) {
0146:                int nameLength = name.length();
0147:                int colonPos = 1 + nameLength;
0148:                char[] buf = new char[colonPos + 1];
0149:                buf[0] = 'L';
0150:                buf[colonPos] = ';';
0151:                name.getChars(0, nameLength, buf, 1);
0152:                for (int i = 1; i != colonPos; ++i) {
0153:                    if (buf[i] == '.') {
0154:                        buf[i] = '/';
0155:                    }
0156:                }
0157:                return new String(buf, 0, colonPos + 1);
0158:            }
0159:
0160:            /**
0161:             * Add a field to the class.
0162:             *
0163:             * @param fieldName the name of the field
0164:             * @param type the type of the field using ...
0165:             * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
0166:             *        bitwise or'd together
0167:             */
0168:            public void addField(String fieldName, String type, short flags) {
0169:                short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
0170:                short typeIndex = itsConstantPool.addUtf8(type);
0171:                itsFields.add(new ClassFileField(fieldNameIndex, typeIndex,
0172:                        flags));
0173:            }
0174:
0175:            /**
0176:             * Add a field to the class.
0177:             *
0178:             * @param fieldName the name of the field
0179:             * @param type the type of the field using ...
0180:             * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
0181:             *        bitwise or'd together
0182:             * @param value an initial integral value
0183:             */
0184:            public void addField(String fieldName, String type, short flags,
0185:                    int value) {
0186:                short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
0187:                short typeIndex = itsConstantPool.addUtf8(type);
0188:                ClassFileField field = new ClassFileField(fieldNameIndex,
0189:                        typeIndex, flags);
0190:                field.setAttributes(itsConstantPool.addUtf8("ConstantValue"),
0191:                        (short) 0, (short) 0, itsConstantPool
0192:                                .addConstant(value));
0193:                itsFields.add(field);
0194:            }
0195:
0196:            /**
0197:             * Add a field to the class.
0198:             *
0199:             * @param fieldName the name of the field
0200:             * @param type the type of the field using ...
0201:             * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
0202:             *        bitwise or'd together
0203:             * @param value an initial long value
0204:             */
0205:            public void addField(String fieldName, String type, short flags,
0206:                    long value) {
0207:                short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
0208:                short typeIndex = itsConstantPool.addUtf8(type);
0209:                ClassFileField field = new ClassFileField(fieldNameIndex,
0210:                        typeIndex, flags);
0211:                field.setAttributes(itsConstantPool.addUtf8("ConstantValue"),
0212:                        (short) 0, (short) 2, itsConstantPool
0213:                                .addConstant(value));
0214:                itsFields.add(field);
0215:            }
0216:
0217:            /**
0218:             * Add a field to the class.
0219:             *
0220:             * @param fieldName the name of the field
0221:             * @param type the type of the field using ...
0222:             * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
0223:             *        bitwise or'd together
0224:             * @param value an initial double value
0225:             */
0226:            public void addField(String fieldName, String type, short flags,
0227:                    double value) {
0228:                short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
0229:                short typeIndex = itsConstantPool.addUtf8(type);
0230:                ClassFileField field = new ClassFileField(fieldNameIndex,
0231:                        typeIndex, flags);
0232:                field.setAttributes(itsConstantPool.addUtf8("ConstantValue"),
0233:                        (short) 0, (short) 2, itsConstantPool
0234:                                .addConstant(value));
0235:                itsFields.add(field);
0236:            }
0237:
0238:            /**
0239:             * Add Information about java variable to use when generating the local
0240:             * variable table.
0241:             *
0242:             * @param name variable name.
0243:             * @param type variable type as bytecode descriptor string.
0244:             * @param startPC the starting bytecode PC where this variable is live,
0245:             *                 or -1 if it does not have a Java register.
0246:             * @param register the Java register number of variable
0247:             *                 or -1 if it does not have a Java register.
0248:             */
0249:            public void addVariableDescriptor(String name, String type,
0250:                    int startPC, int register) {
0251:                int nameIndex = itsConstantPool.addUtf8(name);
0252:                int descriptorIndex = itsConstantPool.addUtf8(type);
0253:                int[] chunk = { nameIndex, descriptorIndex, startPC, register };
0254:                if (itsVarDescriptors == null) {
0255:                    itsVarDescriptors = new ObjArray();
0256:                }
0257:                itsVarDescriptors.add(chunk);
0258:            }
0259:
0260:            /**
0261:             * Add a method and begin adding code.
0262:             *
0263:             * This method must be called before other methods for adding code,
0264:             * exception tables, etc. can be invoked.
0265:             *
0266:             * @param methodName the name of the method
0267:             * @param type a string representing the type
0268:             * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
0269:             *        bitwise or'd together
0270:             */
0271:            public void startMethod(String methodName, String type, short flags) {
0272:                short methodNameIndex = itsConstantPool.addUtf8(methodName);
0273:                short typeIndex = itsConstantPool.addUtf8(type);
0274:                itsCurrentMethod = new ClassFileMethod(methodNameIndex,
0275:                        typeIndex, flags);
0276:                itsMethods.add(itsCurrentMethod);
0277:            }
0278:
0279:            /**
0280:             * Complete generation of the method.
0281:             *
0282:             * After this method is called, no more code can be added to the
0283:             * method begun with <code>startMethod</code>.
0284:             *
0285:             * @param maxLocals the maximum number of local variable slots
0286:             *        (a.k.a. Java registers) used by the method
0287:             */
0288:            public void stopMethod(short maxLocals) {
0289:                if (itsCurrentMethod == null)
0290:                    throw new IllegalStateException("No method to stop");
0291:
0292:                fixLabelGotos();
0293:
0294:                itsMaxLocals = maxLocals;
0295:
0296:                int lineNumberTableLength = 0;
0297:                if (itsLineNumberTable != null) {
0298:                    // 6 bytes for the attribute header
0299:                    // 2 bytes for the line number count
0300:                    // 4 bytes for each entry
0301:                    lineNumberTableLength = 6 + 2 + (itsLineNumberTableTop * 4);
0302:                }
0303:
0304:                int variableTableLength = 0;
0305:                if (itsVarDescriptors != null) {
0306:                    // 6 bytes for the attribute header
0307:                    // 2 bytes for the variable count
0308:                    // 10 bytes for each entry
0309:                    variableTableLength = 6 + 2 + (itsVarDescriptors.size() * 10);
0310:                }
0311:
0312:                int attrLength = 2 + // attribute_name_index
0313:                        4 + // attribute_length
0314:                        2 + // max_stack
0315:                        2 + // max_locals
0316:                        4 + // code_length
0317:                        itsCodeBufferTop + 2 + // exception_table_length
0318:                        (itsExceptionTableTop * 8) + 2 + // attributes_count
0319:                        lineNumberTableLength + variableTableLength;
0320:
0321:                if (attrLength > 65536) {
0322:                    // See http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html,
0323:                    // section 4.10, "The amount of code per non-native, non-abstract 
0324:                    // method is limited to 65536 bytes...
0325:                    throw new ClassFileFormatException(
0326:                            "generated bytecode for method exceeds 64K limit.");
0327:                }
0328:                byte[] codeAttribute = new byte[attrLength];
0329:                int index = 0;
0330:                int codeAttrIndex = itsConstantPool.addUtf8("Code");
0331:                index = putInt16(codeAttrIndex, codeAttribute, index);
0332:                attrLength -= 6; // discount the attribute header
0333:                index = putInt32(attrLength, codeAttribute, index);
0334:                index = putInt16(itsMaxStack, codeAttribute, index);
0335:                index = putInt16(itsMaxLocals, codeAttribute, index);
0336:                index = putInt32(itsCodeBufferTop, codeAttribute, index);
0337:                System.arraycopy(itsCodeBuffer, 0, codeAttribute, index,
0338:                        itsCodeBufferTop);
0339:                index += itsCodeBufferTop;
0340:
0341:                if (itsExceptionTableTop > 0) {
0342:                    index = putInt16(itsExceptionTableTop, codeAttribute, index);
0343:                    for (int i = 0; i < itsExceptionTableTop; i++) {
0344:                        ExceptionTableEntry ete = itsExceptionTable[i];
0345:                        short startPC = (short) getLabelPC(ete.itsStartLabel);
0346:                        short endPC = (short) getLabelPC(ete.itsEndLabel);
0347:                        short handlerPC = (short) getLabelPC(ete.itsHandlerLabel);
0348:                        short catchType = ete.itsCatchType;
0349:                        if (startPC == -1)
0350:                            throw new IllegalStateException(
0351:                                    "start label not defined");
0352:                        if (endPC == -1)
0353:                            throw new IllegalStateException(
0354:                                    "end label not defined");
0355:                        if (handlerPC == -1)
0356:                            throw new IllegalStateException(
0357:                                    "handler label not defined");
0358:
0359:                        index = putInt16(startPC, codeAttribute, index);
0360:                        index = putInt16(endPC, codeAttribute, index);
0361:                        index = putInt16(handlerPC, codeAttribute, index);
0362:                        index = putInt16(catchType, codeAttribute, index);
0363:                    }
0364:                } else {
0365:                    // write 0 as exception table length
0366:                    index = putInt16(0, codeAttribute, index);
0367:                }
0368:
0369:                int attributeCount = 0;
0370:                if (itsLineNumberTable != null)
0371:                    attributeCount++;
0372:                if (itsVarDescriptors != null)
0373:                    attributeCount++;
0374:                index = putInt16(attributeCount, codeAttribute, index);
0375:
0376:                if (itsLineNumberTable != null) {
0377:                    int lineNumberTableAttrIndex = itsConstantPool
0378:                            .addUtf8("LineNumberTable");
0379:                    index = putInt16(lineNumberTableAttrIndex, codeAttribute,
0380:                            index);
0381:                    int tableAttrLength = 2 + (itsLineNumberTableTop * 4);
0382:                    index = putInt32(tableAttrLength, codeAttribute, index);
0383:                    index = putInt16(itsLineNumberTableTop, codeAttribute,
0384:                            index);
0385:                    for (int i = 0; i < itsLineNumberTableTop; i++) {
0386:                        index = putInt32(itsLineNumberTable[i], codeAttribute,
0387:                                index);
0388:                    }
0389:                }
0390:
0391:                if (itsVarDescriptors != null) {
0392:                    int variableTableAttrIndex = itsConstantPool
0393:                            .addUtf8("LocalVariableTable");
0394:                    index = putInt16(variableTableAttrIndex, codeAttribute,
0395:                            index);
0396:                    int varCount = itsVarDescriptors.size();
0397:                    int tableAttrLength = 2 + (varCount * 10);
0398:                    index = putInt32(tableAttrLength, codeAttribute, index);
0399:                    index = putInt16(varCount, codeAttribute, index);
0400:                    for (int i = 0; i < varCount; i++) {
0401:                        int[] chunk = (int[]) itsVarDescriptors.get(i);
0402:                        int nameIndex = chunk[0];
0403:                        int descriptorIndex = chunk[1];
0404:                        int startPC = chunk[2];
0405:                        int register = chunk[3];
0406:                        int length = itsCodeBufferTop - startPC;
0407:
0408:                        index = putInt16(startPC, codeAttribute, index);
0409:                        index = putInt16(length, codeAttribute, index);
0410:                        index = putInt16(nameIndex, codeAttribute, index);
0411:                        index = putInt16(descriptorIndex, codeAttribute, index);
0412:                        index = putInt16(register, codeAttribute, index);
0413:                    }
0414:                }
0415:
0416:                itsCurrentMethod.setCodeAttribute(codeAttribute);
0417:
0418:                itsExceptionTable = null;
0419:                itsExceptionTableTop = 0;
0420:                itsLineNumberTableTop = 0;
0421:                itsCodeBufferTop = 0;
0422:                itsCurrentMethod = null;
0423:                itsMaxStack = 0;
0424:                itsStackTop = 0;
0425:                itsLabelTableTop = 0;
0426:                itsFixupTableTop = 0;
0427:                itsVarDescriptors = null;
0428:            }
0429:
0430:            /**
0431:             * Add the single-byte opcode to the current method.
0432:             *
0433:             * @param theOpCode the opcode of the bytecode
0434:             */
0435:            public void add(int theOpCode) {
0436:                if (opcodeCount(theOpCode) != 0)
0437:                    throw new IllegalArgumentException("Unexpected operands");
0438:                int newStack = itsStackTop + stackChange(theOpCode);
0439:                if (newStack < 0 || Short.MAX_VALUE < newStack)
0440:                    badStack(newStack);
0441:                if (DEBUGCODE)
0442:                    System.out.println("Add " + bytecodeStr(theOpCode));
0443:                addToCodeBuffer(theOpCode);
0444:                itsStackTop = (short) newStack;
0445:                if (newStack > itsMaxStack)
0446:                    itsMaxStack = (short) newStack;
0447:                if (DEBUGSTACK) {
0448:                    System.out.println("After " + bytecodeStr(theOpCode)
0449:                            + " stack = " + itsStackTop);
0450:                }
0451:            }
0452:
0453:            /**
0454:             * Add a single-operand opcode to the current method.
0455:             *
0456:             * @param theOpCode the opcode of the bytecode
0457:             * @param theOperand the operand of the bytecode
0458:             */
0459:            public void add(int theOpCode, int theOperand) {
0460:                if (DEBUGCODE) {
0461:                    System.out.println("Add " + bytecodeStr(theOpCode) + ", "
0462:                            + Integer.toHexString(theOperand));
0463:                }
0464:                int newStack = itsStackTop + stackChange(theOpCode);
0465:                if (newStack < 0 || Short.MAX_VALUE < newStack)
0466:                    badStack(newStack);
0467:
0468:                switch (theOpCode) {
0469:                case ByteCode.GOTO:
0470:                    // fallthru...
0471:                case ByteCode.IFEQ:
0472:                case ByteCode.IFNE:
0473:                case ByteCode.IFLT:
0474:                case ByteCode.IFGE:
0475:                case ByteCode.IFGT:
0476:                case ByteCode.IFLE:
0477:                case ByteCode.IF_ICMPEQ:
0478:                case ByteCode.IF_ICMPNE:
0479:                case ByteCode.IF_ICMPLT:
0480:                case ByteCode.IF_ICMPGE:
0481:                case ByteCode.IF_ICMPGT:
0482:                case ByteCode.IF_ICMPLE:
0483:                case ByteCode.IF_ACMPEQ:
0484:                case ByteCode.IF_ACMPNE:
0485:                case ByteCode.JSR:
0486:                case ByteCode.IFNULL:
0487:                case ByteCode.IFNONNULL: {
0488:                    if ((theOperand & 0x80000000) != 0x80000000) {
0489:                        if ((theOperand < 0) || (theOperand > 65535))
0490:                            throw new IllegalArgumentException(
0491:                                    "Bad label for branch");
0492:                    }
0493:                    int branchPC = itsCodeBufferTop;
0494:                    addToCodeBuffer(theOpCode);
0495:                    if ((theOperand & 0x80000000) != 0x80000000) {
0496:                        // hard displacement
0497:                        addToCodeInt16(theOperand);
0498:                    } else { // a label
0499:                        int targetPC = getLabelPC(theOperand);
0500:                        if (DEBUGLABELS) {
0501:                            int theLabel = theOperand & 0x7FFFFFFF;
0502:                            System.out.println("Fixing branch to " + theLabel
0503:                                    + " at " + targetPC + " from " + branchPC);
0504:                        }
0505:                        if (targetPC != -1) {
0506:                            int offset = targetPC - branchPC;
0507:                            addToCodeInt16(offset);
0508:                        } else {
0509:                            addLabelFixup(theOperand, branchPC + 1);
0510:                            addToCodeInt16(0);
0511:                        }
0512:                    }
0513:                }
0514:                    break;
0515:
0516:                case ByteCode.BIPUSH:
0517:                    if ((byte) theOperand != theOperand)
0518:                        throw new IllegalArgumentException("out of range byte");
0519:                    addToCodeBuffer(theOpCode);
0520:                    addToCodeBuffer((byte) theOperand);
0521:                    break;
0522:
0523:                case ByteCode.SIPUSH:
0524:                    if ((short) theOperand != theOperand)
0525:                        throw new IllegalArgumentException("out of range short");
0526:                    addToCodeBuffer(theOpCode);
0527:                    addToCodeInt16(theOperand);
0528:                    break;
0529:
0530:                case ByteCode.NEWARRAY:
0531:                    if (!(0 <= theOperand && theOperand < 256))
0532:                        throw new IllegalArgumentException("out of range index");
0533:                    addToCodeBuffer(theOpCode);
0534:                    addToCodeBuffer(theOperand);
0535:                    break;
0536:
0537:                case ByteCode.GETFIELD:
0538:                case ByteCode.PUTFIELD:
0539:                    if (!(0 <= theOperand && theOperand < 65536))
0540:                        throw new IllegalArgumentException("out of range field");
0541:                    addToCodeBuffer(theOpCode);
0542:                    addToCodeInt16(theOperand);
0543:                    break;
0544:
0545:                case ByteCode.LDC:
0546:                case ByteCode.LDC_W:
0547:                case ByteCode.LDC2_W:
0548:                    if (!(0 <= theOperand && theOperand < 65536))
0549:                        throw new IllegalArgumentException("out of range index");
0550:                    if (theOperand >= 256 || theOpCode == ByteCode.LDC_W
0551:                            || theOpCode == ByteCode.LDC2_W) {
0552:                        if (theOpCode == ByteCode.LDC) {
0553:                            addToCodeBuffer(ByteCode.LDC_W);
0554:                        } else {
0555:                            addToCodeBuffer(theOpCode);
0556:                        }
0557:                        addToCodeInt16(theOperand);
0558:                    } else {
0559:                        addToCodeBuffer(theOpCode);
0560:                        addToCodeBuffer(theOperand);
0561:                    }
0562:                    break;
0563:
0564:                case ByteCode.RET:
0565:                case ByteCode.ILOAD:
0566:                case ByteCode.LLOAD:
0567:                case ByteCode.FLOAD:
0568:                case ByteCode.DLOAD:
0569:                case ByteCode.ALOAD:
0570:                case ByteCode.ISTORE:
0571:                case ByteCode.LSTORE:
0572:                case ByteCode.FSTORE:
0573:                case ByteCode.DSTORE:
0574:                case ByteCode.ASTORE:
0575:                    if (!(0 <= theOperand && theOperand < 65536))
0576:                        throw new ClassFileFormatException(
0577:                                "out of range variable");
0578:                    if (theOperand >= 256) {
0579:                        addToCodeBuffer(ByteCode.WIDE);
0580:                        addToCodeBuffer(theOpCode);
0581:                        addToCodeInt16(theOperand);
0582:                    } else {
0583:                        addToCodeBuffer(theOpCode);
0584:                        addToCodeBuffer(theOperand);
0585:                    }
0586:                    break;
0587:
0588:                default:
0589:                    throw new IllegalArgumentException(
0590:                            "Unexpected opcode for 1 operand");
0591:                }
0592:
0593:                itsStackTop = (short) newStack;
0594:                if (newStack > itsMaxStack)
0595:                    itsMaxStack = (short) newStack;
0596:                if (DEBUGSTACK) {
0597:                    System.out.println("After " + bytecodeStr(theOpCode)
0598:                            + " stack = " + itsStackTop);
0599:                }
0600:            }
0601:
0602:            /**
0603:             * Generate the load constant bytecode for the given integer.
0604:             *
0605:             * @param k the constant
0606:             */
0607:            public void addLoadConstant(int k) {
0608:                switch (k) {
0609:                case 0:
0610:                    add(ByteCode.ICONST_0);
0611:                    break;
0612:                case 1:
0613:                    add(ByteCode.ICONST_1);
0614:                    break;
0615:                case 2:
0616:                    add(ByteCode.ICONST_2);
0617:                    break;
0618:                case 3:
0619:                    add(ByteCode.ICONST_3);
0620:                    break;
0621:                case 4:
0622:                    add(ByteCode.ICONST_4);
0623:                    break;
0624:                case 5:
0625:                    add(ByteCode.ICONST_5);
0626:                    break;
0627:                default:
0628:                    add(ByteCode.LDC, itsConstantPool.addConstant(k));
0629:                    break;
0630:                }
0631:            }
0632:
0633:            /**
0634:             * Generate the load constant bytecode for the given long.
0635:             *
0636:             * @param k the constant
0637:             */
0638:            public void addLoadConstant(long k) {
0639:                add(ByteCode.LDC2_W, itsConstantPool.addConstant(k));
0640:            }
0641:
0642:            /**
0643:             * Generate the load constant bytecode for the given float.
0644:             *
0645:             * @param k the constant
0646:             */
0647:            public void addLoadConstant(float k) {
0648:                add(ByteCode.LDC, itsConstantPool.addConstant(k));
0649:            }
0650:
0651:            /**
0652:             * Generate the load constant bytecode for the given double.
0653:             *
0654:             * @param k the constant
0655:             */
0656:            public void addLoadConstant(double k) {
0657:                add(ByteCode.LDC2_W, itsConstantPool.addConstant(k));
0658:            }
0659:
0660:            /**
0661:             * Generate the load constant bytecode for the given string.
0662:             *
0663:             * @param k the constant
0664:             */
0665:            public void addLoadConstant(String k) {
0666:                add(ByteCode.LDC, itsConstantPool.addConstant(k));
0667:            }
0668:
0669:            /**
0670:             * Add the given two-operand bytecode to the current method.
0671:             *
0672:             * @param theOpCode the opcode of the bytecode
0673:             * @param theOperand1 the first operand of the bytecode
0674:             * @param theOperand2 the second operand of the bytecode
0675:             */
0676:            public void add(int theOpCode, int theOperand1, int theOperand2) {
0677:                if (DEBUGCODE) {
0678:                    System.out.println("Add " + bytecodeStr(theOpCode) + ", "
0679:                            + Integer.toHexString(theOperand1) + ", "
0680:                            + Integer.toHexString(theOperand2));
0681:                }
0682:                int newStack = itsStackTop + stackChange(theOpCode);
0683:                if (newStack < 0 || Short.MAX_VALUE < newStack)
0684:                    badStack(newStack);
0685:
0686:                if (theOpCode == ByteCode.IINC) {
0687:                    if (!(0 <= theOperand1 && theOperand1 < 65536))
0688:                        throw new ClassFileFormatException(
0689:                                "out of range variable");
0690:                    if (!(0 <= theOperand2 && theOperand2 < 65536))
0691:                        throw new ClassFileFormatException(
0692:                                "out of range increment");
0693:
0694:                    if (theOperand1 > 255 || theOperand2 < -128
0695:                            || theOperand2 > 127) {
0696:                        addToCodeBuffer(ByteCode.WIDE);
0697:                        addToCodeBuffer(ByteCode.IINC);
0698:                        addToCodeInt16(theOperand1);
0699:                        addToCodeInt16(theOperand2);
0700:                    } else {
0701:                        addToCodeBuffer(ByteCode.WIDE);
0702:                        addToCodeBuffer(ByteCode.IINC);
0703:                        addToCodeBuffer(theOperand1);
0704:                        addToCodeBuffer(theOperand2);
0705:                    }
0706:                } else if (theOpCode == ByteCode.MULTIANEWARRAY) {
0707:                    if (!(0 <= theOperand1 && theOperand1 < 65536))
0708:                        throw new IllegalArgumentException("out of range index");
0709:                    if (!(0 <= theOperand2 && theOperand2 < 256))
0710:                        throw new IllegalArgumentException(
0711:                                "out of range dimensions");
0712:
0713:                    addToCodeBuffer(ByteCode.MULTIANEWARRAY);
0714:                    addToCodeInt16(theOperand1);
0715:                    addToCodeBuffer(theOperand2);
0716:                } else {
0717:                    throw new IllegalArgumentException(
0718:                            "Unexpected opcode for 2 operands");
0719:                }
0720:                itsStackTop = (short) newStack;
0721:                if (newStack > itsMaxStack)
0722:                    itsMaxStack = (short) newStack;
0723:                if (DEBUGSTACK) {
0724:                    System.out.println("After " + bytecodeStr(theOpCode)
0725:                            + " stack = " + itsStackTop);
0726:                }
0727:
0728:            }
0729:
0730:            public void add(int theOpCode, String className) {
0731:                if (DEBUGCODE) {
0732:                    System.out.println("Add " + bytecodeStr(theOpCode) + ", "
0733:                            + className);
0734:                }
0735:                int newStack = itsStackTop + stackChange(theOpCode);
0736:                if (newStack < 0 || Short.MAX_VALUE < newStack)
0737:                    badStack(newStack);
0738:                switch (theOpCode) {
0739:                case ByteCode.NEW:
0740:                case ByteCode.ANEWARRAY:
0741:                case ByteCode.CHECKCAST:
0742:                case ByteCode.INSTANCEOF: {
0743:                    short classIndex = itsConstantPool.addClass(className);
0744:                    addToCodeBuffer(theOpCode);
0745:                    addToCodeInt16(classIndex);
0746:                }
0747:                    break;
0748:
0749:                default:
0750:                    throw new IllegalArgumentException(
0751:                            "bad opcode for class reference");
0752:                }
0753:                itsStackTop = (short) newStack;
0754:                if (newStack > itsMaxStack)
0755:                    itsMaxStack = (short) newStack;
0756:                if (DEBUGSTACK) {
0757:                    System.out.println("After " + bytecodeStr(theOpCode)
0758:                            + " stack = " + itsStackTop);
0759:                }
0760:            }
0761:
0762:            public void add(int theOpCode, String className, String fieldName,
0763:                    String fieldType) {
0764:                if (DEBUGCODE) {
0765:                    System.out.println("Add " + bytecodeStr(theOpCode) + ", "
0766:                            + className + ", " + fieldName + ", " + fieldType);
0767:                }
0768:                int newStack = itsStackTop + stackChange(theOpCode);
0769:                char fieldTypeChar = fieldType.charAt(0);
0770:                int fieldSize = (fieldTypeChar == 'J' || fieldTypeChar == 'D') ? 2
0771:                        : 1;
0772:                switch (theOpCode) {
0773:                case ByteCode.GETFIELD:
0774:                case ByteCode.GETSTATIC:
0775:                    newStack += fieldSize;
0776:                    break;
0777:                case ByteCode.PUTSTATIC:
0778:                case ByteCode.PUTFIELD:
0779:                    newStack -= fieldSize;
0780:                    break;
0781:                default:
0782:                    throw new IllegalArgumentException(
0783:                            "bad opcode for field reference");
0784:                }
0785:                if (newStack < 0 || Short.MAX_VALUE < newStack)
0786:                    badStack(newStack);
0787:                short fieldRefIndex = itsConstantPool.addFieldRef(className,
0788:                        fieldName, fieldType);
0789:                addToCodeBuffer(theOpCode);
0790:                addToCodeInt16(fieldRefIndex);
0791:
0792:                itsStackTop = (short) newStack;
0793:                if (newStack > itsMaxStack)
0794:                    itsMaxStack = (short) newStack;
0795:                if (DEBUGSTACK) {
0796:                    System.out.println("After " + bytecodeStr(theOpCode)
0797:                            + " stack = " + itsStackTop);
0798:                }
0799:            }
0800:
0801:            public void addInvoke(int theOpCode, String className,
0802:                    String methodName, String methodType) {
0803:                if (DEBUGCODE) {
0804:                    System.out
0805:                            .println("Add " + bytecodeStr(theOpCode) + ", "
0806:                                    + className + ", " + methodName + ", "
0807:                                    + methodType);
0808:                }
0809:                int parameterInfo = sizeOfParameters(methodType);
0810:                int parameterCount = parameterInfo >>> 16;
0811:                int stackDiff = (short) parameterInfo;
0812:
0813:                int newStack = itsStackTop + stackDiff;
0814:                newStack += stackChange(theOpCode); // adjusts for 'this'
0815:                if (newStack < 0 || Short.MAX_VALUE < newStack)
0816:                    badStack(newStack);
0817:
0818:                switch (theOpCode) {
0819:                case ByteCode.INVOKEVIRTUAL:
0820:                case ByteCode.INVOKESPECIAL:
0821:                case ByteCode.INVOKESTATIC:
0822:                case ByteCode.INVOKEINTERFACE: {
0823:                    addToCodeBuffer(theOpCode);
0824:                    if (theOpCode == ByteCode.INVOKEINTERFACE) {
0825:                        short ifMethodRefIndex = itsConstantPool
0826:                                .addInterfaceMethodRef(className, methodName,
0827:                                        methodType);
0828:                        addToCodeInt16(ifMethodRefIndex);
0829:                        addToCodeBuffer(parameterCount + 1);
0830:                        addToCodeBuffer(0);
0831:                    } else {
0832:                        short methodRefIndex = itsConstantPool.addMethodRef(
0833:                                className, methodName, methodType);
0834:                        addToCodeInt16(methodRefIndex);
0835:                    }
0836:                }
0837:                    break;
0838:
0839:                default:
0840:                    throw new IllegalArgumentException(
0841:                            "bad opcode for method reference");
0842:                }
0843:                itsStackTop = (short) newStack;
0844:                if (newStack > itsMaxStack)
0845:                    itsMaxStack = (short) newStack;
0846:                if (DEBUGSTACK) {
0847:                    System.out.println("After " + bytecodeStr(theOpCode)
0848:                            + " stack = " + itsStackTop);
0849:                }
0850:            }
0851:
0852:            /**
0853:             * Generate code to load the given integer on stack.
0854:             *
0855:             * @param k the constant
0856:             */
0857:            public void addPush(int k) {
0858:                if ((byte) k == k) {
0859:                    if (k == -1) {
0860:                        add(ByteCode.ICONST_M1);
0861:                    } else if (0 <= k && k <= 5) {
0862:                        add((byte) (ByteCode.ICONST_0 + k));
0863:                    } else {
0864:                        add(ByteCode.BIPUSH, (byte) k);
0865:                    }
0866:                } else if ((short) k == k) {
0867:                    add(ByteCode.SIPUSH, (short) k);
0868:                } else {
0869:                    addLoadConstant(k);
0870:                }
0871:            }
0872:
0873:            public void addPush(boolean k) {
0874:                add(k ? ByteCode.ICONST_1 : ByteCode.ICONST_0);
0875:            }
0876:
0877:            /**
0878:             * Generate code to load the given long on stack.
0879:             *
0880:             * @param k the constant
0881:             */
0882:            public void addPush(long k) {
0883:                int ik = (int) k;
0884:                if (ik == k) {
0885:                    addPush(ik);
0886:                    add(ByteCode.I2L);
0887:                } else {
0888:                    addLoadConstant(k);
0889:                }
0890:            }
0891:
0892:            /**
0893:             * Generate code to load the given double on stack.
0894:             *
0895:             * @param k the constant
0896:             */
0897:            public void addPush(double k) {
0898:                if (k == 0.0) {
0899:                    // zero
0900:                    add(ByteCode.DCONST_0);
0901:                    if (1.0 / k < 0) {
0902:                        // Negative zero
0903:                        add(ByteCode.DNEG);
0904:                    }
0905:                } else if (k == 1.0 || k == -1.0) {
0906:                    add(ByteCode.DCONST_1);
0907:                    if (k < 0) {
0908:                        add(ByteCode.DNEG);
0909:                    }
0910:                } else {
0911:                    addLoadConstant(k);
0912:                }
0913:            }
0914:
0915:            /**
0916:             * Generate the code to leave on stack the given string even if the
0917:             * string encoding exeeds the class file limit for single string constant
0918:             *
0919:             * @param k the constant
0920:             */
0921:            public void addPush(String k) {
0922:                int length = k.length();
0923:                int limit = itsConstantPool.getUtfEncodingLimit(k, 0, length);
0924:                if (limit == length) {
0925:                    addLoadConstant(k);
0926:                    return;
0927:                }
0928:                // Split string into picies fitting the UTF limit and generate code for
0929:                // StringBuffer sb = new StringBuffer(length);
0930:                // sb.append(loadConstant(piece_1));
0931:                // ...
0932:                // sb.append(loadConstant(piece_N));
0933:                // sb.toString();
0934:                final String SB = "java/lang/StringBuffer";
0935:                add(ByteCode.NEW, SB);
0936:                add(ByteCode.DUP);
0937:                addPush(length);
0938:                addInvoke(ByteCode.INVOKESPECIAL, SB, "<init>", "(I)V");
0939:                int cursor = 0;
0940:                for (;;) {
0941:                    add(ByteCode.DUP);
0942:                    String s = k.substring(cursor, limit);
0943:                    addLoadConstant(s);
0944:                    addInvoke(ByteCode.INVOKEVIRTUAL, SB, "append",
0945:                            "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0946:                    add(ByteCode.POP);
0947:                    if (limit == length) {
0948:                        break;
0949:                    }
0950:                    cursor = limit;
0951:                    limit = itsConstantPool.getUtfEncodingLimit(k, limit,
0952:                            length);
0953:                }
0954:                addInvoke(ByteCode.INVOKEVIRTUAL, SB, "toString",
0955:                        "()Ljava/lang/String;");
0956:            }
0957:
0958:            /**
0959:             * Check if k fits limit on string constant size imposed by class file
0960:             * format.
0961:             *
0962:             * @param k the string constant
0963:             */
0964:            public boolean isUnderStringSizeLimit(String k) {
0965:                return itsConstantPool.isUnderUtfEncodingLimit(k);
0966:            }
0967:
0968:            /**
0969:             * Store integer from stack top into the given local.
0970:             *
0971:             * @param local number of local register
0972:             */
0973:            public void addIStore(int local) {
0974:                xop(ByteCode.ISTORE_0, ByteCode.ISTORE, local);
0975:            }
0976:
0977:            /**
0978:             * Store long from stack top into the given local.
0979:             *
0980:             * @param local number of local register
0981:             */
0982:            public void addLStore(int local) {
0983:                xop(ByteCode.LSTORE_0, ByteCode.LSTORE, local);
0984:            }
0985:
0986:            /**
0987:             * Store float from stack top into the given local.
0988:             *
0989:             * @param local number of local register
0990:             */
0991:            public void addFStore(int local) {
0992:                xop(ByteCode.FSTORE_0, ByteCode.FSTORE, local);
0993:            }
0994:
0995:            /**
0996:             * Store double from stack top into the given local.
0997:             *
0998:             * @param local number of local register
0999:             */
1000:            public void addDStore(int local) {
1001:                xop(ByteCode.DSTORE_0, ByteCode.DSTORE, local);
1002:            }
1003:
1004:            /**
1005:             * Store object from stack top into the given local.
1006:             *
1007:             * @param local number of local register
1008:             */
1009:            public void addAStore(int local) {
1010:                xop(ByteCode.ASTORE_0, ByteCode.ASTORE, local);
1011:            }
1012:
1013:            /**
1014:             * Load integer from the given local into stack.
1015:             *
1016:             * @param local number of local register
1017:             */
1018:            public void addILoad(int local) {
1019:                xop(ByteCode.ILOAD_0, ByteCode.ILOAD, local);
1020:            }
1021:
1022:            /**
1023:             * Load long from the given local into stack.
1024:             *
1025:             * @param local number of local register
1026:             */
1027:            public void addLLoad(int local) {
1028:                xop(ByteCode.LLOAD_0, ByteCode.LLOAD, local);
1029:            }
1030:
1031:            /**
1032:             * Load float from the given local into stack.
1033:             *
1034:             * @param local number of local register
1035:             */
1036:            public void addFLoad(int local) {
1037:                xop(ByteCode.FLOAD_0, ByteCode.FLOAD, local);
1038:            }
1039:
1040:            /**
1041:             * Load double from the given local into stack.
1042:             *
1043:             * @param local number of local register
1044:             */
1045:            public void addDLoad(int local) {
1046:                xop(ByteCode.DLOAD_0, ByteCode.DLOAD, local);
1047:            }
1048:
1049:            /**
1050:             * Load object from the given local into stack.
1051:             *
1052:             * @param local number of local register
1053:             */
1054:            public void addALoad(int local) {
1055:                xop(ByteCode.ALOAD_0, ByteCode.ALOAD, local);
1056:            }
1057:
1058:            /**
1059:             * Load "this" into stack.
1060:             */
1061:            public void addLoadThis() {
1062:                add(ByteCode.ALOAD_0);
1063:            }
1064:
1065:            private void xop(int shortOp, int op, int local) {
1066:                switch (local) {
1067:                case 0:
1068:                    add(shortOp);
1069:                    break;
1070:                case 1:
1071:                    add(shortOp + 1);
1072:                    break;
1073:                case 2:
1074:                    add(shortOp + 2);
1075:                    break;
1076:                case 3:
1077:                    add(shortOp + 3);
1078:                    break;
1079:                default:
1080:                    add(op, local);
1081:                }
1082:            }
1083:
1084:            public int addTableSwitch(int low, int high) {
1085:                if (DEBUGCODE) {
1086:                    System.out.println("Add "
1087:                            + bytecodeStr(ByteCode.TABLESWITCH) + " " + low
1088:                            + " " + high);
1089:                }
1090:                if (low > high)
1091:                    throw new ClassFileFormatException("Bad bounds: " + low
1092:                            + ' ' + high);
1093:
1094:                int newStack = itsStackTop + stackChange(ByteCode.TABLESWITCH);
1095:                if (newStack < 0 || Short.MAX_VALUE < newStack)
1096:                    badStack(newStack);
1097:
1098:                int entryCount = high - low + 1;
1099:                int padSize = 3 & ~itsCodeBufferTop; // == 3 - itsCodeBufferTop % 4
1100:
1101:                int N = addReservedCodeSpace(1 + padSize + 4
1102:                        * (1 + 2 + entryCount));
1103:                int switchStart = N;
1104:                itsCodeBuffer[N++] = (byte) ByteCode.TABLESWITCH;
1105:                while (padSize != 0) {
1106:                    itsCodeBuffer[N++] = 0;
1107:                    --padSize;
1108:                }
1109:                N += 4; // skip default offset
1110:                N = putInt32(low, itsCodeBuffer, N);
1111:                putInt32(high, itsCodeBuffer, N);
1112:
1113:                itsStackTop = (short) newStack;
1114:                if (newStack > itsMaxStack)
1115:                    itsMaxStack = (short) newStack;
1116:                if (DEBUGSTACK) {
1117:                    System.out.println("After "
1118:                            + bytecodeStr(ByteCode.TABLESWITCH) + " stack = "
1119:                            + itsStackTop);
1120:                }
1121:
1122:                return switchStart;
1123:            }
1124:
1125:            public final void markTableSwitchDefault(int switchStart) {
1126:                setTableSwitchJump(switchStart, -1, itsCodeBufferTop);
1127:            }
1128:
1129:            public final void markTableSwitchCase(int switchStart, int caseIndex) {
1130:                setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop);
1131:            }
1132:
1133:            public final void markTableSwitchCase(int switchStart,
1134:                    int caseIndex, int stackTop) {
1135:                if (!(0 <= stackTop && stackTop <= itsMaxStack))
1136:                    throw new IllegalArgumentException("Bad stack index: "
1137:                            + stackTop);
1138:                itsStackTop = (short) stackTop;
1139:                setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop);
1140:            }
1141:
1142:            public void setTableSwitchJump(int switchStart, int caseIndex,
1143:                    int jumpTarget) {
1144:                if (!(0 <= jumpTarget && jumpTarget <= itsCodeBufferTop))
1145:                    throw new IllegalArgumentException("Bad jump target: "
1146:                            + jumpTarget);
1147:                if (!(caseIndex >= -1))
1148:                    throw new IllegalArgumentException("Bad case index: "
1149:                            + caseIndex);
1150:
1151:                int padSize = 3 & ~switchStart; // == 3 - switchStart % 4
1152:                int caseOffset;
1153:                if (caseIndex < 0) {
1154:                    // default label
1155:                    caseOffset = switchStart + 1 + padSize;
1156:                } else {
1157:                    caseOffset = switchStart + 1 + padSize + 4
1158:                            * (3 + caseIndex);
1159:                }
1160:                if (!(0 <= switchStart && switchStart <= itsCodeBufferTop - 4
1161:                        * 4 - padSize - 1)) {
1162:                    throw new IllegalArgumentException(switchStart
1163:                            + " is outside a possible range of tableswitch"
1164:                            + " in already generated code");
1165:                }
1166:                if ((0xFF & itsCodeBuffer[switchStart]) != ByteCode.TABLESWITCH) {
1167:                    throw new IllegalArgumentException(switchStart
1168:                            + " is not offset of tableswitch statement");
1169:                }
1170:                if (!(0 <= caseOffset && caseOffset + 4 <= itsCodeBufferTop)) {
1171:                    // caseIndex >= -1 does not guarantee that caseOffset >= 0 due
1172:                    // to a possible overflow.
1173:                    throw new ClassFileFormatException("Too big case index: "
1174:                            + caseIndex);
1175:                }
1176:                // ALERT: perhaps check against case bounds?
1177:                putInt32(jumpTarget - switchStart, itsCodeBuffer, caseOffset);
1178:            }
1179:
1180:            public int acquireLabel() {
1181:                int top = itsLabelTableTop;
1182:                if (itsLabelTable == null || top == itsLabelTable.length) {
1183:                    if (itsLabelTable == null) {
1184:                        itsLabelTable = new int[MIN_LABEL_TABLE_SIZE];
1185:                    } else {
1186:                        int[] tmp = new int[itsLabelTable.length * 2];
1187:                        System.arraycopy(itsLabelTable, 0, tmp, 0, top);
1188:                        itsLabelTable = tmp;
1189:                    }
1190:                }
1191:                itsLabelTableTop = top + 1;
1192:                itsLabelTable[top] = -1;
1193:                return top | 0x80000000;
1194:            }
1195:
1196:            public void markLabel(int label) {
1197:                if (!(label < 0))
1198:                    throw new IllegalArgumentException("Bad label, no biscuit");
1199:
1200:                label &= 0x7FFFFFFF;
1201:                if (label > itsLabelTableTop)
1202:                    throw new IllegalArgumentException("Bad label");
1203:
1204:                if (itsLabelTable[label] != -1) {
1205:                    throw new IllegalStateException("Can only mark label once");
1206:                }
1207:
1208:                itsLabelTable[label] = itsCodeBufferTop;
1209:            }
1210:
1211:            public void markLabel(int label, short stackTop) {
1212:                markLabel(label);
1213:                itsStackTop = stackTop;
1214:            }
1215:
1216:            public void markHandler(int theLabel) {
1217:                itsStackTop = 1;
1218:                markLabel(theLabel);
1219:            }
1220:
1221:            private int getLabelPC(int label) {
1222:                if (!(label < 0))
1223:                    throw new IllegalArgumentException("Bad label, no biscuit");
1224:                label &= 0x7FFFFFFF;
1225:                if (!(label < itsLabelTableTop))
1226:                    throw new IllegalArgumentException("Bad label");
1227:                return itsLabelTable[label];
1228:            }
1229:
1230:            private void addLabelFixup(int label, int fixupSite) {
1231:                if (!(label < 0))
1232:                    throw new IllegalArgumentException("Bad label, no biscuit");
1233:                label &= 0x7FFFFFFF;
1234:                if (!(label < itsLabelTableTop))
1235:                    throw new IllegalArgumentException("Bad label");
1236:                int top = itsFixupTableTop;
1237:                if (itsFixupTable == null || top == itsFixupTable.length) {
1238:                    if (itsFixupTable == null) {
1239:                        itsFixupTable = new long[MIN_FIXUP_TABLE_SIZE];
1240:                    } else {
1241:                        long[] tmp = new long[itsFixupTable.length * 2];
1242:                        System.arraycopy(itsFixupTable, 0, tmp, 0, top);
1243:                        itsFixupTable = tmp;
1244:                    }
1245:                }
1246:                itsFixupTableTop = top + 1;
1247:                itsFixupTable[top] = ((long) label << 32) | fixupSite;
1248:            }
1249:
1250:            private void fixLabelGotos() {
1251:                byte[] codeBuffer = itsCodeBuffer;
1252:                for (int i = 0; i < itsFixupTableTop; i++) {
1253:                    long fixup = itsFixupTable[i];
1254:                    int label = (int) (fixup >> 32);
1255:                    int fixupSite = (int) fixup;
1256:                    int pc = itsLabelTable[label];
1257:                    if (pc == -1) {
1258:                        // Unlocated label
1259:                        throw new RuntimeException();
1260:                    }
1261:                    // -1 to get delta from instruction start
1262:                    int offset = pc - (fixupSite - 1);
1263:                    if ((short) offset != offset) {
1264:                        throw new ClassFileFormatException(
1265:                                "Program too complex: too big jump offset");
1266:                    }
1267:                    codeBuffer[fixupSite] = (byte) (offset >> 8);
1268:                    codeBuffer[fixupSite + 1] = (byte) offset;
1269:                }
1270:                itsFixupTableTop = 0;
1271:            }
1272:
1273:            /**
1274:             * Get the current offset into the code of the current method.
1275:             *
1276:             * @return an integer representing the offset
1277:             */
1278:            public int getCurrentCodeOffset() {
1279:                return itsCodeBufferTop;
1280:            }
1281:
1282:            public short getStackTop() {
1283:                return itsStackTop;
1284:            }
1285:
1286:            public void setStackTop(short n) {
1287:                itsStackTop = n;
1288:            }
1289:
1290:            public void adjustStackTop(int delta) {
1291:                int newStack = itsStackTop + delta;
1292:                if (newStack < 0 || Short.MAX_VALUE < newStack)
1293:                    badStack(newStack);
1294:                itsStackTop = (short) newStack;
1295:                if (newStack > itsMaxStack)
1296:                    itsMaxStack = (short) newStack;
1297:                if (DEBUGSTACK) {
1298:                    System.out.println("After " + "adjustStackTop(" + delta
1299:                            + ")" + " stack = " + itsStackTop);
1300:                }
1301:            }
1302:
1303:            private void addToCodeBuffer(int b) {
1304:                int N = addReservedCodeSpace(1);
1305:                itsCodeBuffer[N] = (byte) b;
1306:            }
1307:
1308:            private void addToCodeInt16(int value) {
1309:                int N = addReservedCodeSpace(2);
1310:                putInt16(value, itsCodeBuffer, N);
1311:            }
1312:
1313:            private int addReservedCodeSpace(int size) {
1314:                if (itsCurrentMethod == null)
1315:                    throw new IllegalArgumentException("No method to add to");
1316:                int oldTop = itsCodeBufferTop;
1317:                int newTop = oldTop + size;
1318:                if (newTop > itsCodeBuffer.length) {
1319:                    int newSize = itsCodeBuffer.length * 2;
1320:                    if (newTop > newSize) {
1321:                        newSize = newTop;
1322:                    }
1323:                    byte[] tmp = new byte[newSize];
1324:                    System.arraycopy(itsCodeBuffer, 0, tmp, 0, oldTop);
1325:                    itsCodeBuffer = tmp;
1326:                }
1327:                itsCodeBufferTop = newTop;
1328:                return oldTop;
1329:            }
1330:
1331:            public void addExceptionHandler(int startLabel, int endLabel,
1332:                    int handlerLabel, String catchClassName) {
1333:                if ((startLabel & 0x80000000) != 0x80000000)
1334:                    throw new IllegalArgumentException("Bad startLabel");
1335:                if ((endLabel & 0x80000000) != 0x80000000)
1336:                    throw new IllegalArgumentException("Bad endLabel");
1337:                if ((handlerLabel & 0x80000000) != 0x80000000)
1338:                    throw new IllegalArgumentException("Bad handlerLabel");
1339:
1340:                /*
1341:                 * If catchClassName is null, use 0 for the catch_type_index; which
1342:                 * means catch everything.  (Even when the verifier has let you throw
1343:                 * something other than a Throwable.)
1344:                 */
1345:                short catch_type_index = (catchClassName == null) ? 0
1346:                        : itsConstantPool.addClass(catchClassName);
1347:                ExceptionTableEntry newEntry = new ExceptionTableEntry(
1348:                        startLabel, endLabel, handlerLabel, catch_type_index);
1349:                int N = itsExceptionTableTop;
1350:                if (N == 0) {
1351:                    itsExceptionTable = new ExceptionTableEntry[ExceptionTableSize];
1352:                } else if (N == itsExceptionTable.length) {
1353:                    ExceptionTableEntry[] tmp = new ExceptionTableEntry[N * 2];
1354:                    System.arraycopy(itsExceptionTable, 0, tmp, 0, N);
1355:                    itsExceptionTable = tmp;
1356:                }
1357:                itsExceptionTable[N] = newEntry;
1358:                itsExceptionTableTop = N + 1;
1359:
1360:            }
1361:
1362:            public void addLineNumberEntry(short lineNumber) {
1363:                if (itsCurrentMethod == null)
1364:                    throw new IllegalArgumentException("No method to stop");
1365:                int N = itsLineNumberTableTop;
1366:                if (N == 0) {
1367:                    itsLineNumberTable = new int[LineNumberTableSize];
1368:                } else if (N == itsLineNumberTable.length) {
1369:                    int[] tmp = new int[N * 2];
1370:                    System.arraycopy(itsLineNumberTable, 0, tmp, 0, N);
1371:                    itsLineNumberTable = tmp;
1372:                }
1373:                itsLineNumberTable[N] = (itsCodeBufferTop << 16) + lineNumber;
1374:                itsLineNumberTableTop = N + 1;
1375:            }
1376:
1377:            /**
1378:             * Write the class file to the OutputStream.
1379:             *
1380:             * @param oStream the stream to write to
1381:             * @throws IOException if writing to the stream produces an exception
1382:             */
1383:            public void write(OutputStream oStream) throws IOException {
1384:                byte[] array = toByteArray();
1385:                oStream.write(array);
1386:            }
1387:
1388:            private int getWriteSize() {
1389:                int size = 0;
1390:
1391:                if (itsSourceFileNameIndex != 0) {
1392:                    itsConstantPool.addUtf8("SourceFile");
1393:                }
1394:
1395:                size += 8; //writeLong(FileHeaderConstant);
1396:                size += itsConstantPool.getWriteSize();
1397:                size += 2; //writeShort(itsFlags);
1398:                size += 2; //writeShort(itsThisClassIndex);
1399:                size += 2; //writeShort(itsSuperClassIndex);
1400:                size += 2; //writeShort(itsInterfaces.size());
1401:                size += 2 * itsInterfaces.size();
1402:
1403:                size += 2; //writeShort(itsFields.size());
1404:                for (int i = 0; i < itsFields.size(); i++) {
1405:                    size += ((ClassFileField) (itsFields.get(i)))
1406:                            .getWriteSize();
1407:                }
1408:
1409:                size += 2; //writeShort(itsMethods.size());
1410:                for (int i = 0; i < itsMethods.size(); i++) {
1411:                    size += ((ClassFileMethod) (itsMethods.get(i)))
1412:                            .getWriteSize();
1413:                }
1414:
1415:                if (itsSourceFileNameIndex != 0) {
1416:                    size += 2; //writeShort(1);  attributes count
1417:                    size += 2; //writeShort(sourceFileAttributeNameIndex);
1418:                    size += 4; //writeInt(2);
1419:                    size += 2; //writeShort(itsSourceFileNameIndex);
1420:                } else {
1421:                    size += 2; //out.writeShort(0);  no attributes
1422:                }
1423:
1424:                return size;
1425:            }
1426:
1427:            /**
1428:             * Get the class file as array of bytesto the OutputStream.
1429:             */
1430:            public byte[] toByteArray() {
1431:                int dataSize = getWriteSize();
1432:                byte[] data = new byte[dataSize];
1433:                int offset = 0;
1434:
1435:                short sourceFileAttributeNameIndex = 0;
1436:                if (itsSourceFileNameIndex != 0) {
1437:                    sourceFileAttributeNameIndex = itsConstantPool
1438:                            .addUtf8("SourceFile");
1439:                }
1440:
1441:                offset = putInt64(FileHeaderConstant, data, offset);
1442:                offset = itsConstantPool.write(data, offset);
1443:                offset = putInt16(itsFlags, data, offset);
1444:                offset = putInt16(itsThisClassIndex, data, offset);
1445:                offset = putInt16(itsSuperClassIndex, data, offset);
1446:                offset = putInt16(itsInterfaces.size(), data, offset);
1447:                for (int i = 0; i < itsInterfaces.size(); i++) {
1448:                    int interfaceIndex = ((Short) (itsInterfaces.get(i)))
1449:                            .shortValue();
1450:                    offset = putInt16(interfaceIndex, data, offset);
1451:                }
1452:                offset = putInt16(itsFields.size(), data, offset);
1453:                for (int i = 0; i < itsFields.size(); i++) {
1454:                    ClassFileField field = (ClassFileField) itsFields.get(i);
1455:                    offset = field.write(data, offset);
1456:                }
1457:                offset = putInt16(itsMethods.size(), data, offset);
1458:                for (int i = 0; i < itsMethods.size(); i++) {
1459:                    ClassFileMethod method = (ClassFileMethod) itsMethods
1460:                            .get(i);
1461:                    offset = method.write(data, offset);
1462:                }
1463:                if (itsSourceFileNameIndex != 0) {
1464:                    offset = putInt16(1, data, offset); // attributes count
1465:                    offset = putInt16(sourceFileAttributeNameIndex, data,
1466:                            offset);
1467:                    offset = putInt32(2, data, offset);
1468:                    offset = putInt16(itsSourceFileNameIndex, data, offset);
1469:                } else {
1470:                    offset = putInt16(0, data, offset); // no attributes
1471:                }
1472:
1473:                if (offset != dataSize) {
1474:                    // Check getWriteSize is consistent with write!
1475:                    throw new RuntimeException();
1476:                }
1477:
1478:                return data;
1479:            }
1480:
1481:            static int putInt64(long value, byte[] array, int offset) {
1482:                offset = putInt32((int) (value >>> 32), array, offset);
1483:                return putInt32((int) value, array, offset);
1484:            }
1485:
1486:            private static void badStack(int value) {
1487:                String s;
1488:                if (value < 0) {
1489:                    s = "Stack underflow: " + value;
1490:                } else {
1491:                    s = "Too big stack: " + value;
1492:                }
1493:                throw new IllegalStateException(s);
1494:            }
1495:
1496:            /*
1497:                Really weird. Returns an int with # parameters in hi 16 bits, and
1498:                stack difference removal of parameters from stack and pushing the
1499:                result (it does not take into account removal of this in case of
1500:                non-static methods).
1501:                If Java really supported references we wouldn't have to be this
1502:                perverted.
1503:             */
1504:            private static int sizeOfParameters(String pString) {
1505:                int length = pString.length();
1506:                int rightParenthesis = pString.lastIndexOf(')');
1507:                if (3 <= length /* minimal signature takes at least 3 chars: ()V */
1508:                        && pString.charAt(0) == '(' && 1 <= rightParenthesis
1509:                        && rightParenthesis + 1 < length) {
1510:                    boolean ok = true;
1511:                    int index = 1;
1512:                    int stackDiff = 0;
1513:                    int count = 0;
1514:                    stringLoop: while (index != rightParenthesis) {
1515:                        switch (pString.charAt(index)) {
1516:                        default:
1517:                            ok = false;
1518:                            break stringLoop;
1519:                        case 'J':
1520:                        case 'D':
1521:                            --stackDiff;
1522:                            // fall thru
1523:                        case 'B':
1524:                        case 'S':
1525:                        case 'C':
1526:                        case 'I':
1527:                        case 'Z':
1528:                        case 'F':
1529:                            --stackDiff;
1530:                            ++count;
1531:                            ++index;
1532:                            continue;
1533:                        case '[':
1534:                            ++index;
1535:                            int c = pString.charAt(index);
1536:                            while (c == '[') {
1537:                                ++index;
1538:                                c = pString.charAt(index);
1539:                            }
1540:                            switch (c) {
1541:                            default:
1542:                                ok = false;
1543:                                break stringLoop;
1544:                            case 'J':
1545:                            case 'D':
1546:                            case 'B':
1547:                            case 'S':
1548:                            case 'C':
1549:                            case 'I':
1550:                            case 'Z':
1551:                            case 'F':
1552:                                --stackDiff;
1553:                                ++count;
1554:                                ++index;
1555:                                continue;
1556:                            case 'L':
1557:                                // fall thru
1558:                            }
1559:                            // fall thru
1560:                        case 'L': {
1561:                            --stackDiff;
1562:                            ++count;
1563:                            ++index;
1564:                            int semicolon = pString.indexOf(';', index);
1565:                            if (!(index + 1 <= semicolon && semicolon < rightParenthesis)) {
1566:                                ok = false;
1567:                                break stringLoop;
1568:                            }
1569:                            index = semicolon + 1;
1570:                            continue;
1571:                        }
1572:                        }
1573:                    }
1574:                    if (ok) {
1575:                        switch (pString.charAt(rightParenthesis + 1)) {
1576:                        default:
1577:                            ok = false;
1578:                            break;
1579:                        case 'J':
1580:                        case 'D':
1581:                            ++stackDiff;
1582:                            // fall thru
1583:                        case 'B':
1584:                        case 'S':
1585:                        case 'C':
1586:                        case 'I':
1587:                        case 'Z':
1588:                        case 'F':
1589:                        case 'L':
1590:                        case '[':
1591:                            ++stackDiff;
1592:                            // fall thru
1593:                        case 'V':
1594:                            break;
1595:                        }
1596:                        if (ok) {
1597:                            return ((count << 16) | (0xFFFF & stackDiff));
1598:                        }
1599:                    }
1600:                }
1601:                throw new IllegalArgumentException("Bad parameter signature: "
1602:                        + pString);
1603:            }
1604:
1605:            static int putInt16(int value, byte[] array, int offset) {
1606:                array[offset + 0] = (byte) (value >>> 8);
1607:                array[offset + 1] = (byte) value;
1608:                return offset + 2;
1609:            }
1610:
1611:            static int putInt32(int value, byte[] array, int offset) {
1612:                array[offset + 0] = (byte) (value >>> 24);
1613:                array[offset + 1] = (byte) (value >>> 16);
1614:                array[offset + 2] = (byte) (value >>> 8);
1615:                array[offset + 3] = (byte) value;
1616:                return offset + 4;
1617:            }
1618:
1619:            /**
1620:             * Number of operands accompanying the opcode.
1621:             */
1622:            static int opcodeCount(int opcode) {
1623:                switch (opcode) {
1624:                case ByteCode.AALOAD:
1625:                case ByteCode.AASTORE:
1626:                case ByteCode.ACONST_NULL:
1627:                case ByteCode.ALOAD_0:
1628:                case ByteCode.ALOAD_1:
1629:                case ByteCode.ALOAD_2:
1630:                case ByteCode.ALOAD_3:
1631:                case ByteCode.ARETURN:
1632:                case ByteCode.ARRAYLENGTH:
1633:                case ByteCode.ASTORE_0:
1634:                case ByteCode.ASTORE_1:
1635:                case ByteCode.ASTORE_2:
1636:                case ByteCode.ASTORE_3:
1637:                case ByteCode.ATHROW:
1638:                case ByteCode.BALOAD:
1639:                case ByteCode.BASTORE:
1640:                case ByteCode.BREAKPOINT:
1641:                case ByteCode.CALOAD:
1642:                case ByteCode.CASTORE:
1643:                case ByteCode.D2F:
1644:                case ByteCode.D2I:
1645:                case ByteCode.D2L:
1646:                case ByteCode.DADD:
1647:                case ByteCode.DALOAD:
1648:                case ByteCode.DASTORE:
1649:                case ByteCode.DCMPG:
1650:                case ByteCode.DCMPL:
1651:                case ByteCode.DCONST_0:
1652:                case ByteCode.DCONST_1:
1653:                case ByteCode.DDIV:
1654:                case ByteCode.DLOAD_0:
1655:                case ByteCode.DLOAD_1:
1656:                case ByteCode.DLOAD_2:
1657:                case ByteCode.DLOAD_3:
1658:                case ByteCode.DMUL:
1659:                case ByteCode.DNEG:
1660:                case ByteCode.DREM:
1661:                case ByteCode.DRETURN:
1662:                case ByteCode.DSTORE_0:
1663:                case ByteCode.DSTORE_1:
1664:                case ByteCode.DSTORE_2:
1665:                case ByteCode.DSTORE_3:
1666:                case ByteCode.DSUB:
1667:                case ByteCode.DUP:
1668:                case ByteCode.DUP2:
1669:                case ByteCode.DUP2_X1:
1670:                case ByteCode.DUP2_X2:
1671:                case ByteCode.DUP_X1:
1672:                case ByteCode.DUP_X2:
1673:                case ByteCode.F2D:
1674:                case ByteCode.F2I:
1675:                case ByteCode.F2L:
1676:                case ByteCode.FADD:
1677:                case ByteCode.FALOAD:
1678:                case ByteCode.FASTORE:
1679:                case ByteCode.FCMPG:
1680:                case ByteCode.FCMPL:
1681:                case ByteCode.FCONST_0:
1682:                case ByteCode.FCONST_1:
1683:                case ByteCode.FCONST_2:
1684:                case ByteCode.FDIV:
1685:                case ByteCode.FLOAD_0:
1686:                case ByteCode.FLOAD_1:
1687:                case ByteCode.FLOAD_2:
1688:                case ByteCode.FLOAD_3:
1689:                case ByteCode.FMUL:
1690:                case ByteCode.FNEG:
1691:                case ByteCode.FREM:
1692:                case ByteCode.FRETURN:
1693:                case ByteCode.FSTORE_0:
1694:                case ByteCode.FSTORE_1:
1695:                case ByteCode.FSTORE_2:
1696:                case ByteCode.FSTORE_3:
1697:                case ByteCode.FSUB:
1698:                case ByteCode.I2B:
1699:                case ByteCode.I2C:
1700:                case ByteCode.I2D:
1701:                case ByteCode.I2F:
1702:                case ByteCode.I2L:
1703:                case ByteCode.I2S:
1704:                case ByteCode.IADD:
1705:                case ByteCode.IALOAD:
1706:                case ByteCode.IAND:
1707:                case ByteCode.IASTORE:
1708:                case ByteCode.ICONST_0:
1709:                case ByteCode.ICONST_1:
1710:                case ByteCode.ICONST_2:
1711:                case ByteCode.ICONST_3:
1712:                case ByteCode.ICONST_4:
1713:                case ByteCode.ICONST_5:
1714:                case ByteCode.ICONST_M1:
1715:                case ByteCode.IDIV:
1716:                case ByteCode.ILOAD_0:
1717:                case ByteCode.ILOAD_1:
1718:                case ByteCode.ILOAD_2:
1719:                case ByteCode.ILOAD_3:
1720:                case ByteCode.IMPDEP1:
1721:                case ByteCode.IMPDEP2:
1722:                case ByteCode.IMUL:
1723:                case ByteCode.INEG:
1724:                case ByteCode.IOR:
1725:                case ByteCode.IREM:
1726:                case ByteCode.IRETURN:
1727:                case ByteCode.ISHL:
1728:                case ByteCode.ISHR:
1729:                case ByteCode.ISTORE_0:
1730:                case ByteCode.ISTORE_1:
1731:                case ByteCode.ISTORE_2:
1732:                case ByteCode.ISTORE_3:
1733:                case ByteCode.ISUB:
1734:                case ByteCode.IUSHR:
1735:                case ByteCode.IXOR:
1736:                case ByteCode.L2D:
1737:                case ByteCode.L2F:
1738:                case ByteCode.L2I:
1739:                case ByteCode.LADD:
1740:                case ByteCode.LALOAD:
1741:                case ByteCode.LAND:
1742:                case ByteCode.LASTORE:
1743:                case ByteCode.LCMP:
1744:                case ByteCode.LCONST_0:
1745:                case ByteCode.LCONST_1:
1746:                case ByteCode.LDIV:
1747:                case ByteCode.LLOAD_0:
1748:                case ByteCode.LLOAD_1:
1749:                case ByteCode.LLOAD_2:
1750:                case ByteCode.LLOAD_3:
1751:                case ByteCode.LMUL:
1752:                case ByteCode.LNEG:
1753:                case ByteCode.LOR:
1754:                case ByteCode.LREM:
1755:                case ByteCode.LRETURN:
1756:                case ByteCode.LSHL:
1757:                case ByteCode.LSHR:
1758:                case ByteCode.LSTORE_0:
1759:                case ByteCode.LSTORE_1:
1760:                case ByteCode.LSTORE_2:
1761:                case ByteCode.LSTORE_3:
1762:                case ByteCode.LSUB:
1763:                case ByteCode.LUSHR:
1764:                case ByteCode.LXOR:
1765:                case ByteCode.MONITORENTER:
1766:                case ByteCode.MONITOREXIT:
1767:                case ByteCode.NOP:
1768:                case ByteCode.POP:
1769:                case ByteCode.POP2:
1770:                case ByteCode.RETURN:
1771:                case ByteCode.SALOAD:
1772:                case ByteCode.SASTORE:
1773:                case ByteCode.SWAP:
1774:                case ByteCode.WIDE:
1775:                    return 0;
1776:                case ByteCode.ALOAD:
1777:                case ByteCode.ANEWARRAY:
1778:                case ByteCode.ASTORE:
1779:                case ByteCode.BIPUSH:
1780:                case ByteCode.CHECKCAST:
1781:                case ByteCode.DLOAD:
1782:                case ByteCode.DSTORE:
1783:                case ByteCode.FLOAD:
1784:                case ByteCode.FSTORE:
1785:                case ByteCode.GETFIELD:
1786:                case ByteCode.GETSTATIC:
1787:                case ByteCode.GOTO:
1788:                case ByteCode.GOTO_W:
1789:                case ByteCode.IFEQ:
1790:                case ByteCode.IFGE:
1791:                case ByteCode.IFGT:
1792:                case ByteCode.IFLE:
1793:                case ByteCode.IFLT:
1794:                case ByteCode.IFNE:
1795:                case ByteCode.IFNONNULL:
1796:                case ByteCode.IFNULL:
1797:                case ByteCode.IF_ACMPEQ:
1798:                case ByteCode.IF_ACMPNE:
1799:                case ByteCode.IF_ICMPEQ:
1800:                case ByteCode.IF_ICMPGE:
1801:                case ByteCode.IF_ICMPGT:
1802:                case ByteCode.IF_ICMPLE:
1803:                case ByteCode.IF_ICMPLT:
1804:                case ByteCode.IF_ICMPNE:
1805:                case ByteCode.ILOAD:
1806:                case ByteCode.INSTANCEOF:
1807:                case ByteCode.INVOKEINTERFACE:
1808:                case ByteCode.INVOKESPECIAL:
1809:                case ByteCode.INVOKESTATIC:
1810:                case ByteCode.INVOKEVIRTUAL:
1811:                case ByteCode.ISTORE:
1812:                case ByteCode.JSR:
1813:                case ByteCode.JSR_W:
1814:                case ByteCode.LDC:
1815:                case ByteCode.LDC2_W:
1816:                case ByteCode.LDC_W:
1817:                case ByteCode.LLOAD:
1818:                case ByteCode.LSTORE:
1819:                case ByteCode.NEW:
1820:                case ByteCode.NEWARRAY:
1821:                case ByteCode.PUTFIELD:
1822:                case ByteCode.PUTSTATIC:
1823:                case ByteCode.RET:
1824:                case ByteCode.SIPUSH:
1825:                    return 1;
1826:
1827:                case ByteCode.IINC:
1828:                case ByteCode.MULTIANEWARRAY:
1829:                    return 2;
1830:
1831:                case ByteCode.LOOKUPSWITCH:
1832:                case ByteCode.TABLESWITCH:
1833:                    return -1;
1834:                }
1835:                throw new IllegalArgumentException("Bad opcode: " + opcode);
1836:            }
1837:
1838:            /**
1839:             *  The effect on the operand stack of a given opcode.
1840:             */
1841:            static int stackChange(int opcode) {
1842:                // For INVOKE... accounts only for popping this (unless static),
1843:                // ignoring parameters and return type
1844:                switch (opcode) {
1845:                case ByteCode.DASTORE:
1846:                case ByteCode.LASTORE:
1847:                    return -4;
1848:
1849:                case ByteCode.AASTORE:
1850:                case ByteCode.BASTORE:
1851:                case ByteCode.CASTORE:
1852:                case ByteCode.DCMPG:
1853:                case ByteCode.DCMPL:
1854:                case ByteCode.FASTORE:
1855:                case ByteCode.IASTORE:
1856:                case ByteCode.LCMP:
1857:                case ByteCode.SASTORE:
1858:                    return -3;
1859:
1860:                case ByteCode.DADD:
1861:                case ByteCode.DDIV:
1862:                case ByteCode.DMUL:
1863:                case ByteCode.DREM:
1864:                case ByteCode.DRETURN:
1865:                case ByteCode.DSTORE:
1866:                case ByteCode.DSTORE_0:
1867:                case ByteCode.DSTORE_1:
1868:                case ByteCode.DSTORE_2:
1869:                case ByteCode.DSTORE_3:
1870:                case ByteCode.DSUB:
1871:                case ByteCode.IF_ACMPEQ:
1872:                case ByteCode.IF_ACMPNE:
1873:                case ByteCode.IF_ICMPEQ:
1874:                case ByteCode.IF_ICMPGE:
1875:                case ByteCode.IF_ICMPGT:
1876:                case ByteCode.IF_ICMPLE:
1877:                case ByteCode.IF_ICMPLT:
1878:                case ByteCode.IF_ICMPNE:
1879:                case ByteCode.LADD:
1880:                case ByteCode.LAND:
1881:                case ByteCode.LDIV:
1882:                case ByteCode.LMUL:
1883:                case ByteCode.LOR:
1884:                case ByteCode.LREM:
1885:                case ByteCode.LRETURN:
1886:                case ByteCode.LSTORE:
1887:                case ByteCode.LSTORE_0:
1888:                case ByteCode.LSTORE_1:
1889:                case ByteCode.LSTORE_2:
1890:                case ByteCode.LSTORE_3:
1891:                case ByteCode.LSUB:
1892:                case ByteCode.LXOR:
1893:                case ByteCode.POP2:
1894:                    return -2;
1895:
1896:                case ByteCode.AALOAD:
1897:                case ByteCode.ARETURN:
1898:                case ByteCode.ASTORE:
1899:                case ByteCode.ASTORE_0:
1900:                case ByteCode.ASTORE_1:
1901:                case ByteCode.ASTORE_2:
1902:                case ByteCode.ASTORE_3:
1903:                case ByteCode.ATHROW:
1904:                case ByteCode.BALOAD:
1905:                case ByteCode.CALOAD:
1906:                case ByteCode.D2F:
1907:                case ByteCode.D2I:
1908:                case ByteCode.FADD:
1909:                case ByteCode.FALOAD:
1910:                case ByteCode.FCMPG:
1911:                case ByteCode.FCMPL:
1912:                case ByteCode.FDIV:
1913:                case ByteCode.FMUL:
1914:                case ByteCode.FREM:
1915:                case ByteCode.FRETURN:
1916:                case ByteCode.FSTORE:
1917:                case ByteCode.FSTORE_0:
1918:                case ByteCode.FSTORE_1:
1919:                case ByteCode.FSTORE_2:
1920:                case ByteCode.FSTORE_3:
1921:                case ByteCode.FSUB:
1922:                case ByteCode.GETFIELD:
1923:                case ByteCode.IADD:
1924:                case ByteCode.IALOAD:
1925:                case ByteCode.IAND:
1926:                case ByteCode.IDIV:
1927:                case ByteCode.IFEQ:
1928:                case ByteCode.IFGE:
1929:                case ByteCode.IFGT:
1930:                case ByteCode.IFLE:
1931:                case ByteCode.IFLT:
1932:                case ByteCode.IFNE:
1933:                case ByteCode.IFNONNULL:
1934:                case ByteCode.IFNULL:
1935:                case ByteCode.IMUL:
1936:                case ByteCode.INVOKEINTERFACE: //
1937:                case ByteCode.INVOKESPECIAL: // but needs to account for
1938:                case ByteCode.INVOKEVIRTUAL: // pops 'this' (unless static)
1939:                case ByteCode.IOR:
1940:                case ByteCode.IREM:
1941:                case ByteCode.IRETURN:
1942:                case ByteCode.ISHL:
1943:                case ByteCode.ISHR:
1944:                case ByteCode.ISTORE:
1945:                case ByteCode.ISTORE_0:
1946:                case ByteCode.ISTORE_1:
1947:                case ByteCode.ISTORE_2:
1948:                case ByteCode.ISTORE_3:
1949:                case ByteCode.ISUB:
1950:                case ByteCode.IUSHR:
1951:                case ByteCode.IXOR:
1952:                case ByteCode.L2F:
1953:                case ByteCode.L2I:
1954:                case ByteCode.LOOKUPSWITCH:
1955:                case ByteCode.LSHL:
1956:                case ByteCode.LSHR:
1957:                case ByteCode.LUSHR:
1958:                case ByteCode.MONITORENTER:
1959:                case ByteCode.MONITOREXIT:
1960:                case ByteCode.POP:
1961:                case ByteCode.PUTFIELD:
1962:                case ByteCode.SALOAD:
1963:                case ByteCode.TABLESWITCH:
1964:                    return -1;
1965:
1966:                case ByteCode.ANEWARRAY:
1967:                case ByteCode.ARRAYLENGTH:
1968:                case ByteCode.BREAKPOINT:
1969:                case ByteCode.CHECKCAST:
1970:                case ByteCode.D2L:
1971:                case ByteCode.DALOAD:
1972:                case ByteCode.DNEG:
1973:                case ByteCode.F2I:
1974:                case ByteCode.FNEG:
1975:                case ByteCode.GETSTATIC:
1976:                case ByteCode.GOTO:
1977:                case ByteCode.GOTO_W:
1978:                case ByteCode.I2B:
1979:                case ByteCode.I2C:
1980:                case ByteCode.I2F:
1981:                case ByteCode.I2S:
1982:                case ByteCode.IINC:
1983:                case ByteCode.IMPDEP1:
1984:                case ByteCode.IMPDEP2:
1985:                case ByteCode.INEG:
1986:                case ByteCode.INSTANCEOF:
1987:                case ByteCode.INVOKESTATIC:
1988:                case ByteCode.L2D:
1989:                case ByteCode.LALOAD:
1990:                case ByteCode.LNEG:
1991:                case ByteCode.NEWARRAY:
1992:                case ByteCode.NOP:
1993:                case ByteCode.PUTSTATIC:
1994:                case ByteCode.RET:
1995:                case ByteCode.RETURN:
1996:                case ByteCode.SWAP:
1997:                case ByteCode.WIDE:
1998:                    return 0;
1999:
2000:                case ByteCode.ACONST_NULL:
2001:                case ByteCode.ALOAD:
2002:                case ByteCode.ALOAD_0:
2003:                case ByteCode.ALOAD_1:
2004:                case ByteCode.ALOAD_2:
2005:                case ByteCode.ALOAD_3:
2006:                case ByteCode.BIPUSH:
2007:                case ByteCode.DUP:
2008:                case ByteCode.DUP_X1:
2009:                case ByteCode.DUP_X2:
2010:                case ByteCode.F2D:
2011:                case ByteCode.F2L:
2012:                case ByteCode.FCONST_0:
2013:                case ByteCode.FCONST_1:
2014:                case ByteCode.FCONST_2:
2015:                case ByteCode.FLOAD:
2016:                case ByteCode.FLOAD_0:
2017:                case ByteCode.FLOAD_1:
2018:                case ByteCode.FLOAD_2:
2019:                case ByteCode.FLOAD_3:
2020:                case ByteCode.I2D:
2021:                case ByteCode.I2L:
2022:                case ByteCode.ICONST_0:
2023:                case ByteCode.ICONST_1:
2024:                case ByteCode.ICONST_2:
2025:                case ByteCode.ICONST_3:
2026:                case ByteCode.ICONST_4:
2027:                case ByteCode.ICONST_5:
2028:                case ByteCode.ICONST_M1:
2029:                case ByteCode.ILOAD:
2030:                case ByteCode.ILOAD_0:
2031:                case ByteCode.ILOAD_1:
2032:                case ByteCode.ILOAD_2:
2033:                case ByteCode.ILOAD_3:
2034:                case ByteCode.JSR:
2035:                case ByteCode.JSR_W:
2036:                case ByteCode.LDC:
2037:                case ByteCode.LDC_W:
2038:                case ByteCode.MULTIANEWARRAY:
2039:                case ByteCode.NEW:
2040:                case ByteCode.SIPUSH:
2041:                    return 1;
2042:
2043:                case ByteCode.DCONST_0:
2044:                case ByteCode.DCONST_1:
2045:                case ByteCode.DLOAD:
2046:                case ByteCode.DLOAD_0:
2047:                case ByteCode.DLOAD_1:
2048:                case ByteCode.DLOAD_2:
2049:                case ByteCode.DLOAD_3:
2050:                case ByteCode.DUP2:
2051:                case ByteCode.DUP2_X1:
2052:                case ByteCode.DUP2_X2:
2053:                case ByteCode.LCONST_0:
2054:                case ByteCode.LCONST_1:
2055:                case ByteCode.LDC2_W:
2056:                case ByteCode.LLOAD:
2057:                case ByteCode.LLOAD_0:
2058:                case ByteCode.LLOAD_1:
2059:                case ByteCode.LLOAD_2:
2060:                case ByteCode.LLOAD_3:
2061:                    return 2;
2062:                }
2063:                throw new IllegalArgumentException("Bad opcode: " + opcode);
2064:            }
2065:
2066:            /*
2067:             * Number of bytes of operands generated after the opcode.
2068:             * Not in use currently.
2069:             */
2070:            /*
2071:             int extra(int opcode)
2072:             {
2073:             switch (opcode) {
2074:             case ByteCode.AALOAD:
2075:             case ByteCode.AASTORE:
2076:             case ByteCode.ACONST_NULL:
2077:             case ByteCode.ALOAD_0:
2078:             case ByteCode.ALOAD_1:
2079:             case ByteCode.ALOAD_2:
2080:             case ByteCode.ALOAD_3:
2081:             case ByteCode.ARETURN:
2082:             case ByteCode.ARRAYLENGTH:
2083:             case ByteCode.ASTORE_0:
2084:             case ByteCode.ASTORE_1:
2085:             case ByteCode.ASTORE_2:
2086:             case ByteCode.ASTORE_3:
2087:             case ByteCode.ATHROW:
2088:             case ByteCode.BALOAD:
2089:             case ByteCode.BASTORE:
2090:             case ByteCode.BREAKPOINT:
2091:             case ByteCode.CALOAD:
2092:             case ByteCode.CASTORE:
2093:             case ByteCode.D2F:
2094:             case ByteCode.D2I:
2095:             case ByteCode.D2L:
2096:             case ByteCode.DADD:
2097:             case ByteCode.DALOAD:
2098:             case ByteCode.DASTORE:
2099:             case ByteCode.DCMPG:
2100:             case ByteCode.DCMPL:
2101:             case ByteCode.DCONST_0:
2102:             case ByteCode.DCONST_1:
2103:             case ByteCode.DDIV:
2104:             case ByteCode.DLOAD_0:
2105:             case ByteCode.DLOAD_1:
2106:             case ByteCode.DLOAD_2:
2107:             case ByteCode.DLOAD_3:
2108:             case ByteCode.DMUL:
2109:             case ByteCode.DNEG:
2110:             case ByteCode.DREM:
2111:             case ByteCode.DRETURN:
2112:             case ByteCode.DSTORE_0:
2113:             case ByteCode.DSTORE_1:
2114:             case ByteCode.DSTORE_2:
2115:             case ByteCode.DSTORE_3:
2116:             case ByteCode.DSUB:
2117:             case ByteCode.DUP2:
2118:             case ByteCode.DUP2_X1:
2119:             case ByteCode.DUP2_X2:
2120:             case ByteCode.DUP:
2121:             case ByteCode.DUP_X1:
2122:             case ByteCode.DUP_X2:
2123:             case ByteCode.F2D:
2124:             case ByteCode.F2I:
2125:             case ByteCode.F2L:
2126:             case ByteCode.FADD:
2127:             case ByteCode.FALOAD:
2128:             case ByteCode.FASTORE:
2129:             case ByteCode.FCMPG:
2130:             case ByteCode.FCMPL:
2131:             case ByteCode.FCONST_0:
2132:             case ByteCode.FCONST_1:
2133:             case ByteCode.FCONST_2:
2134:             case ByteCode.FDIV:
2135:             case ByteCode.FLOAD_0:
2136:             case ByteCode.FLOAD_1:
2137:             case ByteCode.FLOAD_2:
2138:             case ByteCode.FLOAD_3:
2139:             case ByteCode.FMUL:
2140:             case ByteCode.FNEG:
2141:             case ByteCode.FREM:
2142:             case ByteCode.FRETURN:
2143:             case ByteCode.FSTORE_0:
2144:             case ByteCode.FSTORE_1:
2145:             case ByteCode.FSTORE_2:
2146:             case ByteCode.FSTORE_3:
2147:             case ByteCode.FSUB:
2148:             case ByteCode.I2B:
2149:             case ByteCode.I2C:
2150:             case ByteCode.I2D:
2151:             case ByteCode.I2F:
2152:             case ByteCode.I2L:
2153:             case ByteCode.I2S:
2154:             case ByteCode.IADD:
2155:             case ByteCode.IALOAD:
2156:             case ByteCode.IAND:
2157:             case ByteCode.IASTORE:
2158:             case ByteCode.ICONST_0:
2159:             case ByteCode.ICONST_1:
2160:             case ByteCode.ICONST_2:
2161:             case ByteCode.ICONST_3:
2162:             case ByteCode.ICONST_4:
2163:             case ByteCode.ICONST_5:
2164:             case ByteCode.ICONST_M1:
2165:             case ByteCode.IDIV:
2166:             case ByteCode.ILOAD_0:
2167:             case ByteCode.ILOAD_1:
2168:             case ByteCode.ILOAD_2:
2169:             case ByteCode.ILOAD_3:
2170:             case ByteCode.IMPDEP1:
2171:             case ByteCode.IMPDEP2:
2172:             case ByteCode.IMUL:
2173:             case ByteCode.INEG:
2174:             case ByteCode.IOR:
2175:             case ByteCode.IREM:
2176:             case ByteCode.IRETURN:
2177:             case ByteCode.ISHL:
2178:             case ByteCode.ISHR:
2179:             case ByteCode.ISTORE_0:
2180:             case ByteCode.ISTORE_1:
2181:             case ByteCode.ISTORE_2:
2182:             case ByteCode.ISTORE_3:
2183:             case ByteCode.ISUB:
2184:             case ByteCode.IUSHR:
2185:             case ByteCode.IXOR:
2186:             case ByteCode.L2D:
2187:             case ByteCode.L2F:
2188:             case ByteCode.L2I:
2189:             case ByteCode.LADD:
2190:             case ByteCode.LALOAD:
2191:             case ByteCode.LAND:
2192:             case ByteCode.LASTORE:
2193:             case ByteCode.LCMP:
2194:             case ByteCode.LCONST_0:
2195:             case ByteCode.LCONST_1:
2196:             case ByteCode.LDIV:
2197:             case ByteCode.LLOAD_0:
2198:             case ByteCode.LLOAD_1:
2199:             case ByteCode.LLOAD_2:
2200:             case ByteCode.LLOAD_3:
2201:             case ByteCode.LMUL:
2202:             case ByteCode.LNEG:
2203:             case ByteCode.LOR:
2204:             case ByteCode.LREM:
2205:             case ByteCode.LRETURN:
2206:             case ByteCode.LSHL:
2207:             case ByteCode.LSHR:
2208:             case ByteCode.LSTORE_0:
2209:             case ByteCode.LSTORE_1:
2210:             case ByteCode.LSTORE_2:
2211:             case ByteCode.LSTORE_3:
2212:             case ByteCode.LSUB:
2213:             case ByteCode.LUSHR:
2214:             case ByteCode.LXOR:
2215:             case ByteCode.MONITORENTER:
2216:             case ByteCode.MONITOREXIT:
2217:             case ByteCode.NOP:
2218:             case ByteCode.POP2:
2219:             case ByteCode.POP:
2220:             case ByteCode.RETURN:
2221:             case ByteCode.SALOAD:
2222:             case ByteCode.SASTORE:
2223:             case ByteCode.SWAP:
2224:             case ByteCode.WIDE:
2225:             return 0;
2226:
2227:             case ByteCode.ALOAD:
2228:             case ByteCode.ASTORE:
2229:             case ByteCode.BIPUSH:
2230:             case ByteCode.DLOAD:
2231:             case ByteCode.DSTORE:
2232:             case ByteCode.FLOAD:
2233:             case ByteCode.FSTORE:
2234:             case ByteCode.ILOAD:
2235:             case ByteCode.ISTORE:
2236:             case ByteCode.LDC:
2237:             case ByteCode.LLOAD:
2238:             case ByteCode.LSTORE:
2239:             case ByteCode.NEWARRAY:
2240:             case ByteCode.RET:
2241:             return 1;
2242:
2243:             case ByteCode.ANEWARRAY:
2244:             case ByteCode.CHECKCAST:
2245:             case ByteCode.GETFIELD:
2246:             case ByteCode.GETSTATIC:
2247:             case ByteCode.GOTO:
2248:             case ByteCode.IFEQ:
2249:             case ByteCode.IFGE:
2250:             case ByteCode.IFGT:
2251:             case ByteCode.IFLE:
2252:             case ByteCode.IFLT:
2253:             case ByteCode.IFNE:
2254:             case ByteCode.IFNONNULL:
2255:             case ByteCode.IFNULL:
2256:             case ByteCode.IF_ACMPEQ:
2257:             case ByteCode.IF_ACMPNE:
2258:             case ByteCode.IF_ICMPEQ:
2259:             case ByteCode.IF_ICMPGE:
2260:             case ByteCode.IF_ICMPGT:
2261:             case ByteCode.IF_ICMPLE:
2262:             case ByteCode.IF_ICMPLT:
2263:             case ByteCode.IF_ICMPNE:
2264:             case ByteCode.IINC:
2265:             case ByteCode.INSTANCEOF:
2266:             case ByteCode.INVOKEINTERFACE:
2267:             case ByteCode.INVOKESPECIAL:
2268:             case ByteCode.INVOKESTATIC:
2269:             case ByteCode.INVOKEVIRTUAL:
2270:             case ByteCode.JSR:
2271:             case ByteCode.LDC2_W:
2272:             case ByteCode.LDC_W:
2273:             case ByteCode.NEW:
2274:             case ByteCode.PUTFIELD:
2275:             case ByteCode.PUTSTATIC:
2276:             case ByteCode.SIPUSH:
2277:             return 2;
2278:
2279:             case ByteCode.MULTIANEWARRAY:
2280:             return 3;
2281:
2282:             case ByteCode.GOTO_W:
2283:             case ByteCode.JSR_W:
2284:             return 4;
2285:
2286:             case ByteCode.LOOKUPSWITCH:    // depends on alignment
2287:             case ByteCode.TABLESWITCH: // depends on alignment
2288:             return -1;
2289:             }
2290:             throw new IllegalArgumentException("Bad opcode: "+opcode);
2291:             }
2292:             */
2293:            private static String bytecodeStr(int code) {
2294:                if (DEBUGSTACK || DEBUGCODE) {
2295:                    switch (code) {
2296:                    case ByteCode.NOP:
2297:                        return "nop";
2298:                    case ByteCode.ACONST_NULL:
2299:                        return "aconst_null";
2300:                    case ByteCode.ICONST_M1:
2301:                        return "iconst_m1";
2302:                    case ByteCode.ICONST_0:
2303:                        return "iconst_0";
2304:                    case ByteCode.ICONST_1:
2305:                        return "iconst_1";
2306:                    case ByteCode.ICONST_2:
2307:                        return "iconst_2";
2308:                    case ByteCode.ICONST_3:
2309:                        return "iconst_3";
2310:                    case ByteCode.ICONST_4:
2311:                        return "iconst_4";
2312:                    case ByteCode.ICONST_5:
2313:                        return "iconst_5";
2314:                    case ByteCode.LCONST_0:
2315:                        return "lconst_0";
2316:                    case ByteCode.LCONST_1:
2317:                        return "lconst_1";
2318:                    case ByteCode.FCONST_0:
2319:                        return "fconst_0";
2320:                    case ByteCode.FCONST_1:
2321:                        return "fconst_1";
2322:                    case ByteCode.FCONST_2:
2323:                        return "fconst_2";
2324:                    case ByteCode.DCONST_0:
2325:                        return "dconst_0";
2326:                    case ByteCode.DCONST_1:
2327:                        return "dconst_1";
2328:                    case ByteCode.BIPUSH:
2329:                        return "bipush";
2330:                    case ByteCode.SIPUSH:
2331:                        return "sipush";
2332:                    case ByteCode.LDC:
2333:                        return "ldc";
2334:                    case ByteCode.LDC_W:
2335:                        return "ldc_w";
2336:                    case ByteCode.LDC2_W:
2337:                        return "ldc2_w";
2338:                    case ByteCode.ILOAD:
2339:                        return "iload";
2340:                    case ByteCode.LLOAD:
2341:                        return "lload";
2342:                    case ByteCode.FLOAD:
2343:                        return "fload";
2344:                    case ByteCode.DLOAD:
2345:                        return "dload";
2346:                    case ByteCode.ALOAD:
2347:                        return "aload";
2348:                    case ByteCode.ILOAD_0:
2349:                        return "iload_0";
2350:                    case ByteCode.ILOAD_1:
2351:                        return "iload_1";
2352:                    case ByteCode.ILOAD_2:
2353:                        return "iload_2";
2354:                    case ByteCode.ILOAD_3:
2355:                        return "iload_3";
2356:                    case ByteCode.LLOAD_0:
2357:                        return "lload_0";
2358:                    case ByteCode.LLOAD_1:
2359:                        return "lload_1";
2360:                    case ByteCode.LLOAD_2:
2361:                        return "lload_2";
2362:                    case ByteCode.LLOAD_3:
2363:                        return "lload_3";
2364:                    case ByteCode.FLOAD_0:
2365:                        return "fload_0";
2366:                    case ByteCode.FLOAD_1:
2367:                        return "fload_1";
2368:                    case ByteCode.FLOAD_2:
2369:                        return "fload_2";
2370:                    case ByteCode.FLOAD_3:
2371:                        return "fload_3";
2372:                    case ByteCode.DLOAD_0:
2373:                        return "dload_0";
2374:                    case ByteCode.DLOAD_1:
2375:                        return "dload_1";
2376:                    case ByteCode.DLOAD_2:
2377:                        return "dload_2";
2378:                    case ByteCode.DLOAD_3:
2379:                        return "dload_3";
2380:                    case ByteCode.ALOAD_0:
2381:                        return "aload_0";
2382:                    case ByteCode.ALOAD_1:
2383:                        return "aload_1";
2384:                    case ByteCode.ALOAD_2:
2385:                        return "aload_2";
2386:                    case ByteCode.ALOAD_3:
2387:                        return "aload_3";
2388:                    case ByteCode.IALOAD:
2389:                        return "iaload";
2390:                    case ByteCode.LALOAD:
2391:                        return "laload";
2392:                    case ByteCode.FALOAD:
2393:                        return "faload";
2394:                    case ByteCode.DALOAD:
2395:                        return "daload";
2396:                    case ByteCode.AALOAD:
2397:                        return "aaload";
2398:                    case ByteCode.BALOAD:
2399:                        return "baload";
2400:                    case ByteCode.CALOAD:
2401:                        return "caload";
2402:                    case ByteCode.SALOAD:
2403:                        return "saload";
2404:                    case ByteCode.ISTORE:
2405:                        return "istore";
2406:                    case ByteCode.LSTORE:
2407:                        return "lstore";
2408:                    case ByteCode.FSTORE:
2409:                        return "fstore";
2410:                    case ByteCode.DSTORE:
2411:                        return "dstore";
2412:                    case ByteCode.ASTORE:
2413:                        return "astore";
2414:                    case ByteCode.ISTORE_0:
2415:                        return "istore_0";
2416:                    case ByteCode.ISTORE_1:
2417:                        return "istore_1";
2418:                    case ByteCode.ISTORE_2:
2419:                        return "istore_2";
2420:                    case ByteCode.ISTORE_3:
2421:                        return "istore_3";
2422:                    case ByteCode.LSTORE_0:
2423:                        return "lstore_0";
2424:                    case ByteCode.LSTORE_1:
2425:                        return "lstore_1";
2426:                    case ByteCode.LSTORE_2:
2427:                        return "lstore_2";
2428:                    case ByteCode.LSTORE_3:
2429:                        return "lstore_3";
2430:                    case ByteCode.FSTORE_0:
2431:                        return "fstore_0";
2432:                    case ByteCode.FSTORE_1:
2433:                        return "fstore_1";
2434:                    case ByteCode.FSTORE_2:
2435:                        return "fstore_2";
2436:                    case ByteCode.FSTORE_3:
2437:                        return "fstore_3";
2438:                    case ByteCode.DSTORE_0:
2439:                        return "dstore_0";
2440:                    case ByteCode.DSTORE_1:
2441:                        return "dstore_1";
2442:                    case ByteCode.DSTORE_2:
2443:                        return "dstore_2";
2444:                    case ByteCode.DSTORE_3:
2445:                        return "dstore_3";
2446:                    case ByteCode.ASTORE_0:
2447:                        return "astore_0";
2448:                    case ByteCode.ASTORE_1:
2449:                        return "astore_1";
2450:                    case ByteCode.ASTORE_2:
2451:                        return "astore_2";
2452:                    case ByteCode.ASTORE_3:
2453:                        return "astore_3";
2454:                    case ByteCode.IASTORE:
2455:                        return "iastore";
2456:                    case ByteCode.LASTORE:
2457:                        return "lastore";
2458:                    case ByteCode.FASTORE:
2459:                        return "fastore";
2460:                    case ByteCode.DASTORE:
2461:                        return "dastore";
2462:                    case ByteCode.AASTORE:
2463:                        return "aastore";
2464:                    case ByteCode.BASTORE:
2465:                        return "bastore";
2466:                    case ByteCode.CASTORE:
2467:                        return "castore";
2468:                    case ByteCode.SASTORE:
2469:                        return "sastore";
2470:                    case ByteCode.POP:
2471:                        return "pop";
2472:                    case ByteCode.POP2:
2473:                        return "pop2";
2474:                    case ByteCode.DUP:
2475:                        return "dup";
2476:                    case ByteCode.DUP_X1:
2477:                        return "dup_x1";
2478:                    case ByteCode.DUP_X2:
2479:                        return "dup_x2";
2480:                    case ByteCode.DUP2:
2481:                        return "dup2";
2482:                    case ByteCode.DUP2_X1:
2483:                        return "dup2_x1";
2484:                    case ByteCode.DUP2_X2:
2485:                        return "dup2_x2";
2486:                    case ByteCode.SWAP:
2487:                        return "swap";
2488:                    case ByteCode.IADD:
2489:                        return "iadd";
2490:                    case ByteCode.LADD:
2491:                        return "ladd";
2492:                    case ByteCode.FADD:
2493:                        return "fadd";
2494:                    case ByteCode.DADD:
2495:                        return "dadd";
2496:                    case ByteCode.ISUB:
2497:                        return "isub";
2498:                    case ByteCode.LSUB:
2499:                        return "lsub";
2500:                    case ByteCode.FSUB:
2501:                        return "fsub";
2502:                    case ByteCode.DSUB:
2503:                        return "dsub";
2504:                    case ByteCode.IMUL:
2505:                        return "imul";
2506:                    case ByteCode.LMUL:
2507:                        return "lmul";
2508:                    case ByteCode.FMUL:
2509:                        return "fmul";
2510:                    case ByteCode.DMUL:
2511:                        return "dmul";
2512:                    case ByteCode.IDIV:
2513:                        return "idiv";
2514:                    case ByteCode.LDIV:
2515:                        return "ldiv";
2516:                    case ByteCode.FDIV:
2517:                        return "fdiv";
2518:                    case ByteCode.DDIV:
2519:                        return "ddiv";
2520:                    case ByteCode.IREM:
2521:                        return "irem";
2522:                    case ByteCode.LREM:
2523:                        return "lrem";
2524:                    case ByteCode.FREM:
2525:                        return "frem";
2526:                    case ByteCode.DREM:
2527:                        return "drem";
2528:                    case ByteCode.INEG:
2529:                        return "ineg";
2530:                    case ByteCode.LNEG:
2531:                        return "lneg";
2532:                    case ByteCode.FNEG:
2533:                        return "fneg";
2534:                    case ByteCode.DNEG:
2535:                        return "dneg";
2536:                    case ByteCode.ISHL:
2537:                        return "ishl";
2538:                    case ByteCode.LSHL:
2539:                        return "lshl";
2540:                    case ByteCode.ISHR:
2541:                        return "ishr";
2542:                    case ByteCode.LSHR:
2543:                        return "lshr";
2544:                    case ByteCode.IUSHR:
2545:                        return "iushr";
2546:                    case ByteCode.LUSHR:
2547:                        return "lushr";
2548:                    case ByteCode.IAND:
2549:                        return "iand";
2550:                    case ByteCode.LAND:
2551:                        return "land";
2552:                    case ByteCode.IOR:
2553:                        return "ior";
2554:                    case ByteCode.LOR:
2555:                        return "lor";
2556:                    case ByteCode.IXOR:
2557:                        return "ixor";
2558:                    case ByteCode.LXOR:
2559:                        return "lxor";
2560:                    case ByteCode.IINC:
2561:                        return "iinc";
2562:                    case ByteCode.I2L:
2563:                        return "i2l";
2564:                    case ByteCode.I2F:
2565:                        return "i2f";
2566:                    case ByteCode.I2D:
2567:                        return "i2d";
2568:                    case ByteCode.L2I:
2569:                        return "l2i";
2570:                    case ByteCode.L2F:
2571:                        return "l2f";
2572:                    case ByteCode.L2D:
2573:                        return "l2d";
2574:                    case ByteCode.F2I:
2575:                        return "f2i";
2576:                    case ByteCode.F2L:
2577:                        return "f2l";
2578:                    case ByteCode.F2D:
2579:                        return "f2d";
2580:                    case ByteCode.D2I:
2581:                        return "d2i";
2582:                    case ByteCode.D2L:
2583:                        return "d2l";
2584:                    case ByteCode.D2F:
2585:                        return "d2f";
2586:                    case ByteCode.I2B:
2587:                        return "i2b";
2588:                    case ByteCode.I2C:
2589:                        return "i2c";
2590:                    case ByteCode.I2S:
2591:                        return "i2s";
2592:                    case ByteCode.LCMP:
2593:                        return "lcmp";
2594:                    case ByteCode.FCMPL:
2595:                        return "fcmpl";
2596:                    case ByteCode.FCMPG:
2597:                        return "fcmpg";
2598:                    case ByteCode.DCMPL:
2599:                        return "dcmpl";
2600:                    case ByteCode.DCMPG:
2601:                        return "dcmpg";
2602:                    case ByteCode.IFEQ:
2603:                        return "ifeq";
2604:                    case ByteCode.IFNE:
2605:                        return "ifne";
2606:                    case ByteCode.IFLT:
2607:                        return "iflt";
2608:                    case ByteCode.IFGE:
2609:                        return "ifge";
2610:                    case ByteCode.IFGT:
2611:                        return "ifgt";
2612:                    case ByteCode.IFLE:
2613:                        return "ifle";
2614:                    case ByteCode.IF_ICMPEQ:
2615:                        return "if_icmpeq";
2616:                    case ByteCode.IF_ICMPNE:
2617:                        return "if_icmpne";
2618:                    case ByteCode.IF_ICMPLT:
2619:                        return "if_icmplt";
2620:                    case ByteCode.IF_ICMPGE:
2621:                        return "if_icmpge";
2622:                    case ByteCode.IF_ICMPGT:
2623:                        return "if_icmpgt";
2624:                    case ByteCode.IF_ICMPLE:
2625:                        return "if_icmple";
2626:                    case ByteCode.IF_ACMPEQ:
2627:                        return "if_acmpeq";
2628:                    case ByteCode.IF_ACMPNE:
2629:                        return "if_acmpne";
2630:                    case ByteCode.GOTO:
2631:                        return "goto";
2632:                    case ByteCode.JSR:
2633:                        return "jsr";
2634:                    case ByteCode.RET:
2635:                        return "ret";
2636:                    case ByteCode.TABLESWITCH:
2637:                        return "tableswitch";
2638:                    case ByteCode.LOOKUPSWITCH:
2639:                        return "lookupswitch";
2640:                    case ByteCode.IRETURN:
2641:                        return "ireturn";
2642:                    case ByteCode.LRETURN:
2643:                        return "lreturn";
2644:                    case ByteCode.FRETURN:
2645:                        return "freturn";
2646:                    case ByteCode.DRETURN:
2647:                        return "dreturn";
2648:                    case ByteCode.ARETURN:
2649:                        return "areturn";
2650:                    case ByteCode.RETURN:
2651:                        return "return";
2652:                    case ByteCode.GETSTATIC:
2653:                        return "getstatic";
2654:                    case ByteCode.PUTSTATIC:
2655:                        return "putstatic";
2656:                    case ByteCode.GETFIELD:
2657:                        return "getfield";
2658:                    case ByteCode.PUTFIELD:
2659:                        return "putfield";
2660:                    case ByteCode.INVOKEVIRTUAL:
2661:                        return "invokevirtual";
2662:                    case ByteCode.INVOKESPECIAL:
2663:                        return "invokespecial";
2664:                    case ByteCode.INVOKESTATIC:
2665:                        return "invokestatic";
2666:                    case ByteCode.INVOKEINTERFACE:
2667:                        return "invokeinterface";
2668:                    case ByteCode.NEW:
2669:                        return "new";
2670:                    case ByteCode.NEWARRAY:
2671:                        return "newarray";
2672:                    case ByteCode.ANEWARRAY:
2673:                        return "anewarray";
2674:                    case ByteCode.ARRAYLENGTH:
2675:                        return "arraylength";
2676:                    case ByteCode.ATHROW:
2677:                        return "athrow";
2678:                    case ByteCode.CHECKCAST:
2679:                        return "checkcast";
2680:                    case ByteCode.INSTANCEOF:
2681:                        return "instanceof";
2682:                    case ByteCode.MONITORENTER:
2683:                        return "monitorenter";
2684:                    case ByteCode.MONITOREXIT:
2685:                        return "monitorexit";
2686:                    case ByteCode.WIDE:
2687:                        return "wide";
2688:                    case ByteCode.MULTIANEWARRAY:
2689:                        return "multianewarray";
2690:                    case ByteCode.IFNULL:
2691:                        return "ifnull";
2692:                    case ByteCode.IFNONNULL:
2693:                        return "ifnonnull";
2694:                    case ByteCode.GOTO_W:
2695:                        return "goto_w";
2696:                    case ByteCode.JSR_W:
2697:                        return "jsr_w";
2698:                    case ByteCode.BREAKPOINT:
2699:                        return "breakpoint";
2700:
2701:                    case ByteCode.IMPDEP1:
2702:                        return "impdep1";
2703:                    case ByteCode.IMPDEP2:
2704:                        return "impdep2";
2705:                    }
2706:                }
2707:                return "";
2708:            }
2709:
2710:            final char[] getCharBuffer(int minimalSize) {
2711:                if (minimalSize > tmpCharBuffer.length) {
2712:                    int newSize = tmpCharBuffer.length * 2;
2713:                    if (minimalSize > newSize) {
2714:                        newSize = minimalSize;
2715:                    }
2716:                    tmpCharBuffer = new char[newSize];
2717:                }
2718:                return tmpCharBuffer;
2719:            }
2720:
2721:            private static final int LineNumberTableSize = 16;
2722:            private static final int ExceptionTableSize = 4;
2723:
2724:            private final static long FileHeaderConstant = 0xCAFEBABE0003002DL;
2725:            // Set DEBUG flags to true to get better checking and progress info.
2726:            private static final boolean DEBUGSTACK = false;
2727:            private static final boolean DEBUGLABELS = false;
2728:            private static final boolean DEBUGCODE = false;
2729:
2730:            private String generatedClassName;
2731:
2732:            private ExceptionTableEntry itsExceptionTable[];
2733:            private int itsExceptionTableTop;
2734:
2735:            private int itsLineNumberTable[]; // pack start_pc & line_number together
2736:            private int itsLineNumberTableTop;
2737:
2738:            private byte[] itsCodeBuffer = new byte[256];
2739:            private int itsCodeBufferTop;
2740:
2741:            private ConstantPool itsConstantPool;
2742:
2743:            private ClassFileMethod itsCurrentMethod;
2744:            private short itsStackTop;
2745:
2746:            private short itsMaxStack;
2747:            private short itsMaxLocals;
2748:
2749:            private ObjArray itsMethods = new ObjArray();
2750:            private ObjArray itsFields = new ObjArray();
2751:            private ObjArray itsInterfaces = new ObjArray();
2752:
2753:            private short itsFlags;
2754:            private short itsThisClassIndex;
2755:            private short itsSuperClassIndex;
2756:            private short itsSourceFileNameIndex;
2757:
2758:            private static final int MIN_LABEL_TABLE_SIZE = 32;
2759:            private int[] itsLabelTable;
2760:            private int itsLabelTableTop;
2761:
2762:            // itsFixupTable[i] = (label_index << 32) | fixup_site
2763:            private static final int MIN_FIXUP_TABLE_SIZE = 40;
2764:            private long[] itsFixupTable;
2765:            private int itsFixupTableTop;
2766:            private ObjArray itsVarDescriptors;
2767:
2768:            private char[] tmpCharBuffer = new char[64];
2769:        }
2770:
2771:        final class ExceptionTableEntry {
2772:
2773:            ExceptionTableEntry(int startLabel, int endLabel, int handlerLabel,
2774:                    short catchType) {
2775:                itsStartLabel = startLabel;
2776:                itsEndLabel = endLabel;
2777:                itsHandlerLabel = handlerLabel;
2778:                itsCatchType = catchType;
2779:            }
2780:
2781:            int itsStartLabel;
2782:            int itsEndLabel;
2783:            int itsHandlerLabel;
2784:            short itsCatchType;
2785:        }
2786:
2787:        final class ClassFileField {
2788:
2789:            ClassFileField(short nameIndex, short typeIndex, short flags) {
2790:                itsNameIndex = nameIndex;
2791:                itsTypeIndex = typeIndex;
2792:                itsFlags = flags;
2793:                itsHasAttributes = false;
2794:            }
2795:
2796:            void setAttributes(short attr1, short attr2, short attr3, int index) {
2797:                itsHasAttributes = true;
2798:                itsAttr1 = attr1;
2799:                itsAttr2 = attr2;
2800:                itsAttr3 = attr3;
2801:                itsIndex = index;
2802:            }
2803:
2804:            int write(byte[] data, int offset) {
2805:                offset = ClassFileWriter.putInt16(itsFlags, data, offset);
2806:                offset = ClassFileWriter.putInt16(itsNameIndex, data, offset);
2807:                offset = ClassFileWriter.putInt16(itsTypeIndex, data, offset);
2808:                if (!itsHasAttributes) {
2809:                    // write 0 attributes
2810:                    offset = ClassFileWriter.putInt16(0, data, offset);
2811:                } else {
2812:                    offset = ClassFileWriter.putInt16(1, data, offset);
2813:                    offset = ClassFileWriter.putInt16(itsAttr1, data, offset);
2814:                    offset = ClassFileWriter.putInt16(itsAttr2, data, offset);
2815:                    offset = ClassFileWriter.putInt16(itsAttr3, data, offset);
2816:                    offset = ClassFileWriter.putInt16(itsIndex, data, offset);
2817:                }
2818:                return offset;
2819:            }
2820:
2821:            int getWriteSize() {
2822:                int size = 2 * 3;
2823:                if (!itsHasAttributes) {
2824:                    size += 2;
2825:                } else {
2826:                    size += 2 + 2 * 4;
2827:                }
2828:                return size;
2829:            }
2830:
2831:            private short itsNameIndex;
2832:            private short itsTypeIndex;
2833:            private short itsFlags;
2834:            private boolean itsHasAttributes;
2835:            private short itsAttr1, itsAttr2, itsAttr3;
2836:            private int itsIndex;
2837:        }
2838:
2839:        final class ClassFileMethod {
2840:
2841:            ClassFileMethod(short nameIndex, short typeIndex, short flags) {
2842:                itsNameIndex = nameIndex;
2843:                itsTypeIndex = typeIndex;
2844:                itsFlags = flags;
2845:            }
2846:
2847:            void setCodeAttribute(byte codeAttribute[]) {
2848:                itsCodeAttribute = codeAttribute;
2849:            }
2850:
2851:            int write(byte[] data, int offset) {
2852:                offset = ClassFileWriter.putInt16(itsFlags, data, offset);
2853:                offset = ClassFileWriter.putInt16(itsNameIndex, data, offset);
2854:                offset = ClassFileWriter.putInt16(itsTypeIndex, data, offset);
2855:                // Code attribute only
2856:                offset = ClassFileWriter.putInt16(1, data, offset);
2857:                System.arraycopy(itsCodeAttribute, 0, data, offset,
2858:                        itsCodeAttribute.length);
2859:                offset += itsCodeAttribute.length;
2860:                return offset;
2861:            }
2862:
2863:            int getWriteSize() {
2864:                return 2 * 4 + itsCodeAttribute.length;
2865:            }
2866:
2867:            private short itsNameIndex;
2868:            private short itsTypeIndex;
2869:            private short itsFlags;
2870:            private byte[] itsCodeAttribute;
2871:
2872:        }
2873:
2874:        final class ConstantPool {
2875:
2876:            ConstantPool(ClassFileWriter cfw) {
2877:                this .cfw = cfw;
2878:                itsTopIndex = 1; // the zero'th entry is reserved
2879:                itsPool = new byte[ConstantPoolSize];
2880:                itsTop = 0;
2881:            }
2882:
2883:            private static final int ConstantPoolSize = 256;
2884:            private static final byte CONSTANT_Class = 7,
2885:                    CONSTANT_Fieldref = 9, CONSTANT_Methodref = 10,
2886:                    CONSTANT_InterfaceMethodref = 11, CONSTANT_String = 8,
2887:                    CONSTANT_Integer = 3, CONSTANT_Float = 4,
2888:                    CONSTANT_Long = 5, CONSTANT_Double = 6,
2889:                    CONSTANT_NameAndType = 12, CONSTANT_Utf8 = 1;
2890:
2891:            int write(byte[] data, int offset) {
2892:                offset = ClassFileWriter.putInt16((short) itsTopIndex, data,
2893:                        offset);
2894:                System.arraycopy(itsPool, 0, data, offset, itsTop);
2895:                offset += itsTop;
2896:                return offset;
2897:            }
2898:
2899:            int getWriteSize() {
2900:                return 2 + itsTop;
2901:            }
2902:
2903:            int addConstant(int k) {
2904:                ensure(5);
2905:                itsPool[itsTop++] = CONSTANT_Integer;
2906:                itsTop = ClassFileWriter.putInt32(k, itsPool, itsTop);
2907:                return (short) (itsTopIndex++);
2908:            }
2909:
2910:            int addConstant(long k) {
2911:                ensure(9);
2912:                itsPool[itsTop++] = CONSTANT_Long;
2913:                itsTop = ClassFileWriter.putInt64(k, itsPool, itsTop);
2914:                int index = itsTopIndex;
2915:                itsTopIndex += 2;
2916:                return index;
2917:            }
2918:
2919:            int addConstant(float k) {
2920:                ensure(5);
2921:                itsPool[itsTop++] = CONSTANT_Float;
2922:                int bits = Float.floatToIntBits(k);
2923:                itsTop = ClassFileWriter.putInt32(bits, itsPool, itsTop);
2924:                return itsTopIndex++;
2925:            }
2926:
2927:            int addConstant(double k) {
2928:                ensure(9);
2929:                itsPool[itsTop++] = CONSTANT_Double;
2930:                long bits = Double.doubleToLongBits(k);
2931:                itsTop = ClassFileWriter.putInt64(bits, itsPool, itsTop);
2932:                int index = itsTopIndex;
2933:                itsTopIndex += 2;
2934:                return index;
2935:            }
2936:
2937:            int addConstant(String k) {
2938:                int utf8Index = 0xFFFF & addUtf8(k);
2939:                int theIndex = itsStringConstHash.getInt(utf8Index, -1);
2940:                if (theIndex == -1) {
2941:                    theIndex = itsTopIndex++;
2942:                    ensure(3);
2943:                    itsPool[itsTop++] = CONSTANT_String;
2944:                    itsTop = ClassFileWriter.putInt16(utf8Index, itsPool,
2945:                            itsTop);
2946:                    itsStringConstHash.put(utf8Index, theIndex);
2947:                }
2948:                return theIndex;
2949:            }
2950:
2951:            boolean isUnderUtfEncodingLimit(String s) {
2952:                int strLen = s.length();
2953:                if (strLen * 3 <= MAX_UTF_ENCODING_SIZE) {
2954:                    return true;
2955:                } else if (strLen > MAX_UTF_ENCODING_SIZE) {
2956:                    return false;
2957:                }
2958:                return strLen == getUtfEncodingLimit(s, 0, strLen);
2959:            }
2960:
2961:            /**
2962:             * Get maximum i such that <tt>start <= i <= end</tt> and
2963:             * <tt>s.substring(start, i)</tt> fits JVM UTF string encoding limit.
2964:             */
2965:            int getUtfEncodingLimit(String s, int start, int end) {
2966:                if ((end - start) * 3 <= MAX_UTF_ENCODING_SIZE) {
2967:                    return end;
2968:                }
2969:                int limit = MAX_UTF_ENCODING_SIZE;
2970:                for (int i = start; i != end; i++) {
2971:                    int c = s.charAt(i);
2972:                    if (0 != c && c <= 0x7F) {
2973:                        --limit;
2974:                    } else if (c < 0x7FF) {
2975:                        limit -= 2;
2976:                    } else {
2977:                        limit -= 3;
2978:                    }
2979:                    if (limit < 0) {
2980:                        return i;
2981:                    }
2982:                }
2983:                return end;
2984:            }
2985:
2986:            short addUtf8(String k) {
2987:                int theIndex = itsUtf8Hash.get(k, -1);
2988:                if (theIndex == -1) {
2989:                    int strLen = k.length();
2990:                    boolean tooBigString;
2991:                    if (strLen > MAX_UTF_ENCODING_SIZE) {
2992:                        tooBigString = true;
2993:                    } else {
2994:                        tooBigString = false;
2995:                        // Ask for worst case scenario buffer when each char takes 3
2996:                        // bytes
2997:                        ensure(1 + 2 + strLen * 3);
2998:                        int top = itsTop;
2999:
3000:                        itsPool[top++] = CONSTANT_Utf8;
3001:                        top += 2; // skip length
3002:
3003:                        char[] chars = cfw.getCharBuffer(strLen);
3004:                        k.getChars(0, strLen, chars, 0);
3005:
3006:                        for (int i = 0; i != strLen; i++) {
3007:                            int c = chars[i];
3008:                            if (c != 0 && c <= 0x7F) {
3009:                                itsPool[top++] = (byte) c;
3010:                            } else if (c > 0x7FF) {
3011:                                itsPool[top++] = (byte) (0xE0 | (c >> 12));
3012:                                itsPool[top++] = (byte) (0x80 | ((c >> 6) & 0x3F));
3013:                                itsPool[top++] = (byte) (0x80 | (c & 0x3F));
3014:                            } else {
3015:                                itsPool[top++] = (byte) (0xC0 | (c >> 6));
3016:                                itsPool[top++] = (byte) (0x80 | (c & 0x3F));
3017:                            }
3018:                        }
3019:
3020:                        int utfLen = top - (itsTop + 1 + 2);
3021:                        if (utfLen > MAX_UTF_ENCODING_SIZE) {
3022:                            tooBigString = true;
3023:                        } else {
3024:                            // Write back length
3025:                            itsPool[itsTop + 1] = (byte) (utfLen >>> 8);
3026:                            itsPool[itsTop + 2] = (byte) utfLen;
3027:
3028:                            itsTop = top;
3029:                            theIndex = itsTopIndex++;
3030:                            itsUtf8Hash.put(k, theIndex);
3031:                        }
3032:                    }
3033:                    if (tooBigString) {
3034:                        throw new IllegalArgumentException("Too big string");
3035:                    }
3036:                }
3037:                return (short) theIndex;
3038:            }
3039:
3040:            private short addNameAndType(String name, String type) {
3041:                short nameIndex = addUtf8(name);
3042:                short typeIndex = addUtf8(type);
3043:                ensure(5);
3044:                itsPool[itsTop++] = CONSTANT_NameAndType;
3045:                itsTop = ClassFileWriter.putInt16(nameIndex, itsPool, itsTop);
3046:                itsTop = ClassFileWriter.putInt16(typeIndex, itsPool, itsTop);
3047:                return (short) (itsTopIndex++);
3048:            }
3049:
3050:            short addClass(String className) {
3051:                int theIndex = itsClassHash.get(className, -1);
3052:                if (theIndex == -1) {
3053:                    String slashed = className;
3054:                    if (className.indexOf('.') > 0) {
3055:                        slashed = ClassFileWriter.getSlashedForm(className);
3056:                        theIndex = itsClassHash.get(slashed, -1);
3057:                        if (theIndex != -1) {
3058:                            itsClassHash.put(className, theIndex);
3059:                        }
3060:                    }
3061:                    if (theIndex == -1) {
3062:                        int utf8Index = addUtf8(slashed);
3063:                        ensure(3);
3064:                        itsPool[itsTop++] = CONSTANT_Class;
3065:                        itsTop = ClassFileWriter.putInt16(utf8Index, itsPool,
3066:                                itsTop);
3067:                        theIndex = itsTopIndex++;
3068:                        itsClassHash.put(slashed, theIndex);
3069:                        if (className != slashed) {
3070:                            itsClassHash.put(className, theIndex);
3071:                        }
3072:                    }
3073:                }
3074:                return (short) theIndex;
3075:            }
3076:
3077:            short addFieldRef(String className, String fieldName,
3078:                    String fieldType) {
3079:                FieldOrMethodRef ref = new FieldOrMethodRef(className,
3080:                        fieldName, fieldType);
3081:
3082:                int theIndex = itsFieldRefHash.get(ref, -1);
3083:                if (theIndex == -1) {
3084:                    short ntIndex = addNameAndType(fieldName, fieldType);
3085:                    short classIndex = addClass(className);
3086:                    ensure(5);
3087:                    itsPool[itsTop++] = CONSTANT_Fieldref;
3088:                    itsTop = ClassFileWriter.putInt16(classIndex, itsPool,
3089:                            itsTop);
3090:                    itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop);
3091:                    theIndex = itsTopIndex++;
3092:                    itsFieldRefHash.put(ref, theIndex);
3093:                }
3094:                return (short) theIndex;
3095:            }
3096:
3097:            short addMethodRef(String className, String methodName,
3098:                    String methodType) {
3099:                FieldOrMethodRef ref = new FieldOrMethodRef(className,
3100:                        methodName, methodType);
3101:
3102:                int theIndex = itsMethodRefHash.get(ref, -1);
3103:                if (theIndex == -1) {
3104:                    short ntIndex = addNameAndType(methodName, methodType);
3105:                    short classIndex = addClass(className);
3106:                    ensure(5);
3107:                    itsPool[itsTop++] = CONSTANT_Methodref;
3108:                    itsTop = ClassFileWriter.putInt16(classIndex, itsPool,
3109:                            itsTop);
3110:                    itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop);
3111:                    theIndex = itsTopIndex++;
3112:                    itsMethodRefHash.put(ref, theIndex);
3113:                }
3114:                return (short) theIndex;
3115:            }
3116:
3117:            short addInterfaceMethodRef(String className, String methodName,
3118:                    String methodType) {
3119:                short ntIndex = addNameAndType(methodName, methodType);
3120:                short classIndex = addClass(className);
3121:                ensure(5);
3122:                itsPool[itsTop++] = CONSTANT_InterfaceMethodref;
3123:                itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop);
3124:                itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop);
3125:                return (short) (itsTopIndex++);
3126:            }
3127:
3128:            void ensure(int howMuch) {
3129:                if (itsTop + howMuch > itsPool.length) {
3130:                    int newCapacity = itsPool.length * 2;
3131:                    if (itsTop + howMuch > newCapacity) {
3132:                        newCapacity = itsTop + howMuch;
3133:                    }
3134:                    byte[] tmp = new byte[newCapacity];
3135:                    System.arraycopy(itsPool, 0, tmp, 0, itsTop);
3136:                    itsPool = tmp;
3137:                }
3138:            }
3139:
3140:            private ClassFileWriter cfw;
3141:
3142:            private static final int MAX_UTF_ENCODING_SIZE = 65535;
3143:
3144:            private UintMap itsStringConstHash = new UintMap();
3145:            private ObjToIntMap itsUtf8Hash = new ObjToIntMap();
3146:            private ObjToIntMap itsFieldRefHash = new ObjToIntMap();
3147:            private ObjToIntMap itsMethodRefHash = new ObjToIntMap();
3148:            private ObjToIntMap itsClassHash = new ObjToIntMap();
3149:
3150:            private int itsTop;
3151:            private int itsTopIndex;
3152:            private byte itsPool[];
3153:        }
3154:
3155:        final class FieldOrMethodRef {
3156:            FieldOrMethodRef(String className, String name, String type) {
3157:                this .className = className;
3158:                this .name = name;
3159:                this .type = type;
3160:            }
3161:
3162:            public boolean equals(Object obj) {
3163:                if (!(obj instanceof  FieldOrMethodRef)) {
3164:                    return false;
3165:                }
3166:                FieldOrMethodRef x = (FieldOrMethodRef) obj;
3167:                return className.equals(x.className) && name.equals(x.name)
3168:                        && type.equals(x.type);
3169:            }
3170:
3171:            public int hashCode() {
3172:                if (hashCode == -1) {
3173:                    int h1 = className.hashCode();
3174:                    int h2 = name.hashCode();
3175:                    int h3 = type.hashCode();
3176:                    hashCode = h1 ^ h2 ^ h3;
3177:                }
3178:                return hashCode;
3179:            }
3180:
3181:            private String className;
3182:            private String name;
3183:            private String type;
3184:            private int hashCode = -1;
3185:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.