Source Code Cross Referenced for CodeWriter.java in  » Scripting » beanshell » bsh » org » objectweb » asm » 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 » beanshell » bsh.org.objectweb.asm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /***
0002:         * ASM: a very small and fast Java bytecode manipulation framework
0003:         * Copyright (C) 2000 INRIA, France Telecom
0004:         * Copyright (C) 2002 France Telecom
0005:         *
0006:         * This library is free software; you can redistribute it and/or
0007:         * modify it under the terms of the GNU Lesser General Public
0008:         * License as published by the Free Software Foundation; either
0009:         * version 2 of the License, or (at your option) any later version.
0010:         *
0011:         * This library is distributed in the hope that it will be useful,
0012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014:         * Lesser General Public License for more details.
0015:         *
0016:         * You should have received a copy of the GNU Lesser General Public
0017:         * License along with this library; if not, write to the Free Software
0018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019:         *
0020:         * Contact: Eric.Bruneton@rd.francetelecom.com
0021:         *
0022:         * Author: Eric Bruneton
0023:         */package bsh.org.objectweb.asm;
0024:
0025:        /**
0026:         * A {@link CodeVisitor CodeVisitor} that generates Java bytecode instructions.
0027:         * Each visit method of this class appends the bytecode corresponding to the
0028:         * visited instruction to a byte vector, in the order these methods are called.
0029:         */
0030:
0031:        public class CodeWriter implements  CodeVisitor {
0032:
0033:            /**
0034:             * <tt>true</tt> if preconditions must be checked at runtime or not.
0035:             */
0036:
0037:            final static boolean CHECK = false;
0038:
0039:            /**
0040:             * Next code writer (see {@link ClassWriter#firstMethod firstMethod}).
0041:             */
0042:
0043:            CodeWriter next;
0044:
0045:            /**
0046:             * The class writer to which this method must be added.
0047:             */
0048:
0049:            private ClassWriter cw;
0050:
0051:            /**
0052:             * The constant pool item that contains the name of this method.
0053:             */
0054:
0055:            private Item name;
0056:
0057:            /**
0058:             * The constant pool item that contains the descriptor of this method.
0059:             */
0060:
0061:            private Item desc;
0062:
0063:            /**
0064:             * Access flags of this method.
0065:             */
0066:
0067:            private int access;
0068:
0069:            /**
0070:             * Maximum stack size of this method.
0071:             */
0072:
0073:            private int maxStack;
0074:
0075:            /**
0076:             * Maximum number of local variables for this method.
0077:             */
0078:
0079:            private int maxLocals;
0080:
0081:            /**
0082:             * The bytecode of this method.
0083:             */
0084:
0085:            private ByteVector code = new ByteVector();
0086:
0087:            /**
0088:             * Number of entries in the catch table of this method.
0089:             */
0090:
0091:            private int catchCount;
0092:
0093:            /**
0094:             * The catch table of this method.
0095:             */
0096:
0097:            private ByteVector catchTable;
0098:
0099:            /**
0100:             * Number of exceptions that can be thrown by this method.
0101:             */
0102:
0103:            private int exceptionCount;
0104:
0105:            /**
0106:             * The exceptions that can be thrown by this method. More
0107:             * precisely, this array contains the indexes of the constant pool items
0108:             * that contain the internal names of these exception classes.
0109:             */
0110:
0111:            private int[] exceptions;
0112:
0113:            /**
0114:             * Number of entries in the LocalVariableTable attribute.
0115:             */
0116:
0117:            private int localVarCount;
0118:
0119:            /**
0120:             * The LocalVariableTable attribute.
0121:             */
0122:
0123:            private ByteVector localVar;
0124:
0125:            /**
0126:             * Number of entries in the LineNumberTable attribute.
0127:             */
0128:
0129:            private int lineNumberCount;
0130:
0131:            /**
0132:             * The LineNumberTable attribute.
0133:             */
0134:
0135:            private ByteVector lineNumber;
0136:
0137:            /**
0138:             * Indicates if some jump instructions are too small and need to be resized.
0139:             */
0140:
0141:            private boolean resize;
0142:
0143:            // --------------------------------------------------------------------------
0144:            // Fields for the control flow graph analysis algorithm (used to compute the
0145:            // maximum stack size). A control flow graph contains one node per "basic
0146:            // block", and one edge per "jump" from one basic block to another. Each node
0147:            // (i.e., each basic block) is represented by the Label object that
0148:            // corresponds to the first instruction of this basic block. Each node also
0149:            // stores the list of its successors in the graph, as a linked list of Edge
0150:            // objects.
0151:            // --------------------------------------------------------------------------
0152:
0153:            /**
0154:             * <tt>true</tt> if the maximum stack size and number of local variables must
0155:             * be automatically computed.
0156:             */
0157:
0158:            private final boolean computeMaxs;
0159:
0160:            /**
0161:             * The (relative) stack size after the last visited instruction. This size is
0162:             * relative to the beginning of the current basic block, i.e., the true stack
0163:             * size after the last visited instruction is equal to the {@link
0164:             * Label#beginStackSize beginStackSize} of the current basic block plus
0165:             * <tt>stackSize</tt>.
0166:             */
0167:
0168:            private int stackSize;
0169:
0170:            /**
0171:             * The (relative) maximum stack size after the last visited instruction. This
0172:             * size is relative to the beginning of the current basic block, i.e., the
0173:             * true maximum stack size after the last visited instruction is equal to the
0174:             * {@link Label#beginStackSize beginStackSize} of the current basic block plus
0175:             * <tt>stackSize</tt>.
0176:             */
0177:
0178:            private int maxStackSize;
0179:
0180:            /**
0181:             * The current basic block. This block is the basic block to which the next
0182:             * instruction to be visited must be added.
0183:             */
0184:
0185:            private Label currentBlock;
0186:
0187:            /**
0188:             * The basic block stack used by the control flow analysis algorithm. This
0189:             * stack is represented by a linked list of {@link Label Label} objects,
0190:             * linked to each other by their {@link Label#next} field. This stack must
0191:             * not be confused with the JVM stack used to execute the JVM instructions!
0192:             */
0193:
0194:            private Label blockStack;
0195:
0196:            /**
0197:             * The stack size variation corresponding to each JVM instruction. This stack
0198:             * variation is equal to the size of the values produced by an instruction,
0199:             * minus the size of the values consumed by this instruction.
0200:             */
0201:
0202:            private final static int[] SIZE;
0203:
0204:            // --------------------------------------------------------------------------
0205:            // Fields to optimize the creation of {@link Edge Edge} objects by using a
0206:            // pool of reusable objects. The (shared) pool is a linked list of Edge
0207:            // objects, linked to each other by their {@link Edge#poolNext} field. Each
0208:            // time a CodeWriter needs to allocate an Edge, it removes the first Edge
0209:            // of the pool and adds it to a private list of Edge objects. After the end
0210:            // of the control flow analysis algorithm, the Edge objects in the private
0211:            // list of the CodeWriter are added back to the pool (by appending this
0212:            // private list to the pool list; in order to do this in constant time, both
0213:            // head and tail of the private list are stored in this CodeWriter).
0214:            // --------------------------------------------------------------------------
0215:
0216:            /**
0217:             * The head of the list of {@link Edge Edge} objects used by this {@link
0218:             * CodeWriter CodeWriter}. These objects, linked to each other by their
0219:             * {@link Edge#poolNext} field, are added back to the shared pool at the
0220:             * end of the control flow analysis algorithm.
0221:             */
0222:
0223:            private Edge head;
0224:
0225:            /**
0226:             * The tail of the list of {@link Edge Edge} objects used by this {@link
0227:             * CodeWriter CodeWriter}. These objects, linked to each other by their
0228:             * {@link Edge#poolNext} field, are added back to the shared pool at the
0229:             * end of the control flow analysis algorithm.
0230:             */
0231:
0232:            private Edge tail;
0233:
0234:            /**
0235:             * The shared pool of {@link Edge Edge} objects. This pool is a linked list
0236:             * of Edge objects, linked to each other by their {@link Edge#poolNext} field.
0237:             */
0238:
0239:            private static Edge pool;
0240:
0241:            // --------------------------------------------------------------------------
0242:            // Static initializer
0243:            // --------------------------------------------------------------------------
0244:
0245:            /**
0246:             * Computes the stack size variation corresponding to each JVM instruction.
0247:             */
0248:
0249:            static {
0250:                int i;
0251:                int[] b = new int[202];
0252:                String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE"
0253:                        + "EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF"
0254:                        + "DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
0255:                for (i = 0; i < b.length; ++i) {
0256:                    b[i] = s.charAt(i) - 'E';
0257:                }
0258:                SIZE = b;
0259:
0260:                /* code to generate the above string
0261:
0262:                int NA = 0; // not applicable (unused opcode or variable size opcode)
0263:
0264:                b = new int[] {
0265:                  0,  //NOP,             // visitInsn
0266:                  1,  //ACONST_NULL,     // -
0267:                  1,  //ICONST_M1,       // -
0268:                  1,  //ICONST_0,        // -
0269:                  1,  //ICONST_1,        // -
0270:                  1,  //ICONST_2,        // -
0271:                  1,  //ICONST_3,        // -
0272:                  1,  //ICONST_4,        // -
0273:                  1,  //ICONST_5,        // -
0274:                  2,  //LCONST_0,        // -
0275:                  2,  //LCONST_1,        // -
0276:                  1,  //FCONST_0,        // -
0277:                  1,  //FCONST_1,        // -
0278:                  1,  //FCONST_2,        // -
0279:                  2,  //DCONST_0,        // -
0280:                  2,  //DCONST_1,        // -
0281:                  1,  //BIPUSH,          // visitIntInsn
0282:                  1,  //SIPUSH,          // -
0283:                  1,  //LDC,             // visitLdcInsn
0284:                  NA, //LDC_W,           // -
0285:                  NA, //LDC2_W,          // -
0286:                  1,  //ILOAD,           // visitVarInsn
0287:                  2,  //LLOAD,           // -
0288:                  1,  //FLOAD,           // -
0289:                  2,  //DLOAD,           // -
0290:                  1,  //ALOAD,           // -
0291:                  NA, //ILOAD_0,         // -
0292:                  NA, //ILOAD_1,         // -
0293:                  NA, //ILOAD_2,         // -
0294:                  NA, //ILOAD_3,         // -
0295:                  NA, //LLOAD_0,         // -
0296:                  NA, //LLOAD_1,         // -
0297:                  NA, //LLOAD_2,         // -
0298:                  NA, //LLOAD_3,         // -
0299:                  NA, //FLOAD_0,         // -
0300:                  NA, //FLOAD_1,         // -
0301:                  NA, //FLOAD_2,         // -
0302:                  NA, //FLOAD_3,         // -
0303:                  NA, //DLOAD_0,         // -
0304:                  NA, //DLOAD_1,         // -
0305:                  NA, //DLOAD_2,         // -
0306:                  NA, //DLOAD_3,         // -
0307:                  NA, //ALOAD_0,         // -
0308:                  NA, //ALOAD_1,         // -
0309:                  NA, //ALOAD_2,         // -
0310:                  NA, //ALOAD_3,         // -
0311:                  -1, //IALOAD,          // visitInsn
0312:                  0,  //LALOAD,          // -
0313:                  -1, //FALOAD,          // -
0314:                  0,  //DALOAD,          // -
0315:                  -1, //AALOAD,          // -
0316:                  -1, //BALOAD,          // -
0317:                  -1, //CALOAD,          // -
0318:                  -1, //SALOAD,          // -
0319:                  -1, //ISTORE,          // visitVarInsn
0320:                  -2, //LSTORE,          // -
0321:                  -1, //FSTORE,          // -
0322:                  -2, //DSTORE,          // -
0323:                  -1, //ASTORE,          // -
0324:                  NA, //ISTORE_0,        // -
0325:                  NA, //ISTORE_1,        // -
0326:                  NA, //ISTORE_2,        // -
0327:                  NA, //ISTORE_3,        // -
0328:                  NA, //LSTORE_0,        // -
0329:                  NA, //LSTORE_1,        // -
0330:                  NA, //LSTORE_2,        // -
0331:                  NA, //LSTORE_3,        // -
0332:                  NA, //FSTORE_0,        // -
0333:                  NA, //FSTORE_1,        // -
0334:                  NA, //FSTORE_2,        // -
0335:                  NA, //FSTORE_3,        // -
0336:                  NA, //DSTORE_0,        // -
0337:                  NA, //DSTORE_1,        // -
0338:                  NA, //DSTORE_2,        // -
0339:                  NA, //DSTORE_3,        // -
0340:                  NA, //ASTORE_0,        // -
0341:                  NA, //ASTORE_1,        // -
0342:                  NA, //ASTORE_2,        // -
0343:                  NA, //ASTORE_3,        // -
0344:                  -3, //IASTORE,         // visitInsn
0345:                  -4, //LASTORE,         // -
0346:                  -3, //FASTORE,         // -
0347:                  -4, //DASTORE,         // -
0348:                  -3, //AASTORE,         // -
0349:                  -3, //BASTORE,         // -
0350:                  -3, //CASTORE,         // -
0351:                  -3, //SASTORE,         // -
0352:                  -1, //POP,             // -
0353:                  -2, //POP2,            // -
0354:                  1,  //DUP,             // -
0355:                  1,  //DUP_X1,          // -
0356:                  1,  //DUP_X2,          // -
0357:                  2,  //DUP2,            // -
0358:                  2,  //DUP2_X1,         // -
0359:                  2,  //DUP2_X2,         // -
0360:                  0,  //SWAP,            // -
0361:                  -1, //IADD,            // -
0362:                  -2, //LADD,            // -
0363:                  -1, //FADD,            // -
0364:                  -2, //DADD,            // -
0365:                  -1, //ISUB,            // -
0366:                  -2, //LSUB,            // -
0367:                  -1, //FSUB,            // -
0368:                  -2, //DSUB,            // -
0369:                  -1, //IMUL,            // -
0370:                  -2, //LMUL,            // -
0371:                  -1, //FMUL,            // -
0372:                  -2, //DMUL,            // -
0373:                  -1, //IDIV,            // -
0374:                  -2, //LDIV,            // -
0375:                  -1, //FDIV,            // -
0376:                  -2, //DDIV,            // -
0377:                  -1, //IREM,            // -
0378:                  -2, //LREM,            // -
0379:                  -1, //FREM,            // -
0380:                  -2, //DREM,            // -
0381:                  0,  //INEG,            // -
0382:                  0,  //LNEG,            // -
0383:                  0,  //FNEG,            // -
0384:                  0,  //DNEG,            // -
0385:                  -1, //ISHL,            // -
0386:                  -1, //LSHL,            // -
0387:                  -1, //ISHR,            // -
0388:                  -1, //LSHR,            // -
0389:                  -1, //IUSHR,           // -
0390:                  -1, //LUSHR,           // -
0391:                  -1, //IAND,            // -
0392:                  -2, //LAND,            // -
0393:                  -1, //IOR,             // -
0394:                  -2, //LOR,             // -
0395:                  -1, //IXOR,            // -
0396:                  -2, //LXOR,            // -
0397:                  0,  //IINC,            // visitIincInsn
0398:                  1,  //I2L,             // visitInsn
0399:                  0,  //I2F,             // -
0400:                  1,  //I2D,             // -
0401:                  -1, //L2I,             // -
0402:                  -1, //L2F,             // -
0403:                  0,  //L2D,             // -
0404:                  0,  //F2I,             // -
0405:                  1,  //F2L,             // -
0406:                  1,  //F2D,             // -
0407:                  -1, //D2I,             // -
0408:                  0,  //D2L,             // -
0409:                  -1, //D2F,             // -
0410:                  0,  //I2B,             // -
0411:                  0,  //I2C,             // -
0412:                  0,  //I2S,             // -
0413:                  -3, //LCMP,            // -
0414:                  -1, //FCMPL,           // -
0415:                  -1, //FCMPG,           // -
0416:                  -3, //DCMPL,           // -
0417:                  -3, //DCMPG,           // -
0418:                  -1, //IFEQ,            // visitJumpInsn
0419:                  -1, //IFNE,            // -
0420:                  -1, //IFLT,            // -
0421:                  -1, //IFGE,            // -
0422:                  -1, //IFGT,            // -
0423:                  -1, //IFLE,            // -
0424:                  -2, //IF_ICMPEQ,       // -
0425:                  -2, //IF_ICMPNE,       // -
0426:                  -2, //IF_ICMPLT,       // -
0427:                  -2, //IF_ICMPGE,       // -
0428:                  -2, //IF_ICMPGT,       // -
0429:                  -2, //IF_ICMPLE,       // -
0430:                  -2, //IF_ACMPEQ,       // -
0431:                  -2, //IF_ACMPNE,       // -
0432:                  0,  //GOTO,            // -
0433:                  1,  //JSR,             // -
0434:                  0,  //RET,             // visitVarInsn
0435:                  -1, //TABLESWITCH,     // visiTableSwitchInsn
0436:                  -1, //LOOKUPSWITCH,    // visitLookupSwitch
0437:                  -1, //IRETURN,         // visitInsn
0438:                  -2, //LRETURN,         // -
0439:                  -1, //FRETURN,         // -
0440:                  -2, //DRETURN,         // -
0441:                  -1, //ARETURN,         // -
0442:                  0,  //RETURN,          // -
0443:                  NA, //GETSTATIC,       // visitFieldInsn
0444:                  NA, //PUTSTATIC,       // -
0445:                  NA, //GETFIELD,        // -
0446:                  NA, //PUTFIELD,        // -
0447:                  NA, //INVOKEVIRTUAL,   // visitMethodInsn
0448:                  NA, //INVOKESPECIAL,   // -
0449:                  NA, //INVOKESTATIC,    // -
0450:                  NA, //INVOKEINTERFACE, // -
0451:                  NA, //UNUSED,          // NOT VISITED
0452:                  1,  //NEW,             // visitTypeInsn
0453:                  0,  //NEWARRAY,        // visitIntInsn
0454:                  0,  //ANEWARRAY,       // visitTypeInsn
0455:                  0,  //ARRAYLENGTH,     // visitInsn
0456:                  NA, //ATHROW,          // -
0457:                  0,  //CHECKCAST,       // visitTypeInsn
0458:                  0,  //INSTANCEOF,      // -
0459:                  -1, //MONITORENTER,    // visitInsn
0460:                  -1, //MONITOREXIT,     // -
0461:                  NA, //WIDE,            // NOT VISITED
0462:                  NA, //MULTIANEWARRAY,  // visitMultiANewArrayInsn
0463:                  -1, //IFNULL,          // visitJumpInsn
0464:                  -1, //IFNONNULL,       // -
0465:                  NA, //GOTO_W,          // -
0466:                  NA, //JSR_W,           // -
0467:                };
0468:                for (i = 0; i < b.length; ++i) {
0469:                  System.err.print((char)('E' + b[i]));
0470:                }
0471:                System.err.println();
0472:                 */
0473:            }
0474:
0475:            // --------------------------------------------------------------------------
0476:            // Constructor
0477:            // --------------------------------------------------------------------------
0478:
0479:            /**
0480:             * Constructs a CodeWriter.
0481:             *
0482:             * @param cw the class writer in which the method must be added.
0483:             * @param computeMaxs <tt>true</tt> if the maximum stack size and number of
0484:             *      local variables must be automatically computed.
0485:             */
0486:
0487:            protected CodeWriter(final ClassWriter cw, final boolean computeMaxs) {
0488:                if (cw.firstMethod == null) {
0489:                    cw.firstMethod = this ;
0490:                    cw.lastMethod = this ;
0491:                } else {
0492:                    cw.lastMethod.next = this ;
0493:                    cw.lastMethod = this ;
0494:                }
0495:                this .cw = cw;
0496:                this .computeMaxs = computeMaxs;
0497:                if (computeMaxs) {
0498:                    // pushes the first block onto the stack of blocks to be visited
0499:                    currentBlock = new Label();
0500:                    currentBlock.pushed = true;
0501:                    blockStack = currentBlock;
0502:                }
0503:            }
0504:
0505:            /**
0506:             * Initializes this CodeWriter to define the bytecode of the specified method.
0507:             *
0508:             * @param access the method's access flags (see {@link Constants}).
0509:             * @param name the method's name.
0510:             * @param desc the method's descriptor (see {@link Type Type}).
0511:             * @param exceptions the internal names of the method's exceptions. May be
0512:             *      <tt>null</tt>.
0513:             */
0514:
0515:            protected void init(final int access, final String name,
0516:                    final String desc, final String[] exceptions) {
0517:                this .access = access;
0518:                this .name = cw.newUTF8(name);
0519:                this .desc = cw.newUTF8(desc);
0520:                if (exceptions != null && exceptions.length > 0) {
0521:                    exceptionCount = exceptions.length;
0522:                    this .exceptions = new int[exceptionCount];
0523:                    for (int i = 0; i < exceptionCount; ++i) {
0524:                        this .exceptions[i] = cw.newClass(exceptions[i]).index;
0525:                    }
0526:                }
0527:                if (computeMaxs) {
0528:                    // updates maxLocals
0529:                    int size = getArgumentsAndReturnSizes(desc) >> 2;
0530:                    if ((access & Constants.ACC_STATIC) != 0) {
0531:                        --size;
0532:                    }
0533:                    if (size > maxLocals) {
0534:                        maxLocals = size;
0535:                    }
0536:                }
0537:            }
0538:
0539:            // --------------------------------------------------------------------------
0540:            // Implementation of the CodeVisitor interface
0541:            // --------------------------------------------------------------------------
0542:
0543:            public void visitInsn(final int opcode) {
0544:                if (computeMaxs) {
0545:                    // updates current and max stack sizes
0546:                    int size = stackSize + SIZE[opcode];
0547:                    if (size > maxStackSize) {
0548:                        maxStackSize = size;
0549:                    }
0550:                    stackSize = size;
0551:                    // if opcode == ATHROW or xRETURN, ends current block (no successor)
0552:                    if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN)
0553:                            || opcode == Constants.ATHROW) {
0554:                        if (currentBlock != null) {
0555:                            currentBlock.maxStackSize = maxStackSize;
0556:                            currentBlock = null;
0557:                        }
0558:                    }
0559:                }
0560:                // adds the instruction to the bytecode of the method
0561:                code.put1(opcode);
0562:            }
0563:
0564:            public void visitIntInsn(final int opcode, final int operand) {
0565:                if (computeMaxs && opcode != Constants.NEWARRAY) {
0566:                    // updates current and max stack sizes only if opcode == NEWARRAY
0567:                    // (stack size variation = 0 for BIPUSH or SIPUSH)
0568:                    int size = stackSize + 1;
0569:                    if (size > maxStackSize) {
0570:                        maxStackSize = size;
0571:                    }
0572:                    stackSize = size;
0573:                }
0574:                // adds the instruction to the bytecode of the method
0575:                if (opcode == Constants.SIPUSH) {
0576:                    code.put12(opcode, operand);
0577:                } else { // BIPUSH or NEWARRAY
0578:                    code.put11(opcode, operand);
0579:                }
0580:            }
0581:
0582:            public void visitVarInsn(final int opcode, final int var) {
0583:                if (computeMaxs) {
0584:                    // updates current and max stack sizes
0585:                    if (opcode == Constants.RET) {
0586:                        // no stack change, but end of current block (no successor)
0587:                        if (currentBlock != null) {
0588:                            currentBlock.maxStackSize = maxStackSize;
0589:                            currentBlock = null;
0590:                        }
0591:                    } else { // xLOAD or xSTORE
0592:                        int size = stackSize + SIZE[opcode];
0593:                        if (size > maxStackSize) {
0594:                            maxStackSize = size;
0595:                        }
0596:                        stackSize = size;
0597:                    }
0598:                    // updates max locals
0599:                    int n;
0600:                    if (opcode == Constants.LLOAD || opcode == Constants.DLOAD
0601:                            || opcode == Constants.LSTORE
0602:                            || opcode == Constants.DSTORE) {
0603:                        n = var + 2;
0604:                    } else {
0605:                        n = var + 1;
0606:                    }
0607:                    if (n > maxLocals) {
0608:                        maxLocals = n;
0609:                    }
0610:                }
0611:                // adds the instruction to the bytecode of the method
0612:                if (var < 4 && opcode != Constants.RET) {
0613:                    int opt;
0614:                    if (opcode < Constants.ISTORE) {
0615:                        opt = 26 /*ILOAD_0*/
0616:                                + ((opcode - Constants.ILOAD) << 2) + var;
0617:                    } else {
0618:                        opt = 59 /*ISTORE_0*/
0619:                                + ((opcode - Constants.ISTORE) << 2) + var;
0620:                    }
0621:                    code.put1(opt);
0622:                } else if (var >= 256) {
0623:                    code.put1(196 /*WIDE*/).put12(opcode, var);
0624:                } else {
0625:                    code.put11(opcode, var);
0626:                }
0627:            }
0628:
0629:            public void visitTypeInsn(final int opcode, final String desc) {
0630:                if (computeMaxs && opcode == Constants.NEW) {
0631:                    // updates current and max stack sizes only if opcode == NEW
0632:                    // (stack size variation = 0 for ANEWARRAY, CHECKCAST, INSTANCEOF)
0633:                    int size = stackSize + 1;
0634:                    if (size > maxStackSize) {
0635:                        maxStackSize = size;
0636:                    }
0637:                    stackSize = size;
0638:                }
0639:                // adds the instruction to the bytecode of the method
0640:                code.put12(opcode, cw.newClass(desc).index);
0641:            }
0642:
0643:            public void visitFieldInsn(final int opcode, final String owner,
0644:                    final String name, final String desc) {
0645:                if (computeMaxs) {
0646:                    int size;
0647:                    // computes the stack size variation
0648:                    char c = desc.charAt(0);
0649:                    switch (opcode) {
0650:                    case Constants.GETSTATIC:
0651:                        size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
0652:                        break;
0653:                    case Constants.PUTSTATIC:
0654:                        size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
0655:                        break;
0656:                    case Constants.GETFIELD:
0657:                        size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
0658:                        break;
0659:                    //case Constants.PUTFIELD:
0660:                    default:
0661:                        size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
0662:                        break;
0663:                    }
0664:                    // updates current and max stack sizes
0665:                    if (size > maxStackSize) {
0666:                        maxStackSize = size;
0667:                    }
0668:                    stackSize = size;
0669:                }
0670:                // adds the instruction to the bytecode of the method
0671:                code.put12(opcode, cw.newField(owner, name, desc).index);
0672:            }
0673:
0674:            public void visitMethodInsn(final int opcode, final String owner,
0675:                    final String name, final String desc) {
0676:                Item i;
0677:                if (opcode == Constants.INVOKEINTERFACE) {
0678:                    i = cw.newItfMethod(owner, name, desc);
0679:                } else {
0680:                    i = cw.newMethod(owner, name, desc);
0681:                }
0682:                int argSize = i.intVal;
0683:                if (computeMaxs) {
0684:                    // computes the stack size variation. In order not to recompute several
0685:                    // times this variation for the same Item, we use the intVal field of
0686:                    // this item to store this variation, once it has been computed. More
0687:                    // precisely this intVal field stores the sizes of the arguments and of
0688:                    // the return value corresponding to desc.
0689:                    if (argSize == 0) {
0690:                        // the above sizes have not been computed yet, so we compute them...
0691:                        argSize = getArgumentsAndReturnSizes(desc);
0692:                        // ... and we save them in order not to recompute them in the future
0693:                        i.intVal = argSize;
0694:                    }
0695:                    int size;
0696:                    if (opcode == Constants.INVOKESTATIC) {
0697:                        size = stackSize - (argSize >> 2) + (argSize & 0x03)
0698:                                + 1;
0699:                    } else {
0700:                        size = stackSize - (argSize >> 2) + (argSize & 0x03);
0701:                    }
0702:                    // updates current and max stack sizes
0703:                    if (size > maxStackSize) {
0704:                        maxStackSize = size;
0705:                    }
0706:                    stackSize = size;
0707:                }
0708:                // adds the instruction to the bytecode of the method
0709:                if (opcode == Constants.INVOKEINTERFACE) {
0710:                    if (!computeMaxs) {
0711:                        if (argSize == 0) {
0712:                            argSize = getArgumentsAndReturnSizes(desc);
0713:                            i.intVal = argSize;
0714:                        }
0715:                    }
0716:                    code.put12(Constants.INVOKEINTERFACE, i.index).put11(
0717:                            argSize >> 2, 0);
0718:                } else {
0719:                    code.put12(opcode, i.index);
0720:                }
0721:            }
0722:
0723:            public void visitJumpInsn(final int opcode, final Label label) {
0724:                if (CHECK) {
0725:                    if (label.owner == null) {
0726:                        label.owner = this ;
0727:                    } else if (label.owner != this ) {
0728:                        throw new IllegalArgumentException();
0729:                    }
0730:                }
0731:                if (computeMaxs) {
0732:                    if (opcode == Constants.GOTO) {
0733:                        // no stack change, but end of current block (with one new successor)
0734:                        if (currentBlock != null) {
0735:                            currentBlock.maxStackSize = maxStackSize;
0736:                            addSuccessor(stackSize, label);
0737:                            currentBlock = null;
0738:                        }
0739:                    } else if (opcode == Constants.JSR) {
0740:                        if (currentBlock != null) {
0741:                            addSuccessor(stackSize + 1, label);
0742:                        }
0743:                    } else {
0744:                        // updates current stack size (max stack size unchanged because stack
0745:                        // size variation always negative in this case)
0746:                        stackSize += SIZE[opcode];
0747:                        if (currentBlock != null) {
0748:                            addSuccessor(stackSize, label);
0749:                        }
0750:                    }
0751:                }
0752:                // adds the instruction to the bytecode of the method
0753:                if (label.resolved
0754:                        && label.position - code.length < Short.MIN_VALUE) {
0755:                    // case of a backward jump with an offset < -32768. In this case we
0756:                    // automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx <l>
0757:                    // with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the "opposite" opcode
0758:                    // of IFxxx (i.e., IFNE for IFEQ) and where <l'> designates the
0759:                    // instruction just after the GOTO_W.
0760:                    if (opcode == Constants.GOTO) {
0761:                        code.put1(200); // GOTO_W
0762:                    } else if (opcode == Constants.JSR) {
0763:                        code.put1(201); // JSR_W
0764:                    } else {
0765:                        code.put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
0766:                                : opcode ^ 1);
0767:                        code.put2(8); // jump offset
0768:                        code.put1(200); // GOTO_W
0769:                    }
0770:                    label.put(this , code, code.length - 1, true);
0771:                } else {
0772:                    // case of a backward jump with an offset >= -32768, or of a forward jump
0773:                    // with, of course, an unknown offset. In these cases we store the offset
0774:                    // in 2 bytes (which will be increased in resizeInstructions, if needed).
0775:                    code.put1(opcode);
0776:                    label.put(this , code, code.length - 1, false);
0777:                }
0778:            }
0779:
0780:            public void visitLabel(final Label label) {
0781:                if (CHECK) {
0782:                    if (label.owner == null) {
0783:                        label.owner = this ;
0784:                    } else if (label.owner != this ) {
0785:                        throw new IllegalArgumentException();
0786:                    }
0787:                }
0788:                if (computeMaxs) {
0789:                    if (currentBlock != null) {
0790:                        // ends current block (with one new successor)
0791:                        currentBlock.maxStackSize = maxStackSize;
0792:                        addSuccessor(stackSize, label);
0793:                    }
0794:                    // begins a new current block,
0795:                    // resets the relative current and max stack sizes
0796:                    currentBlock = label;
0797:                    stackSize = 0;
0798:                    maxStackSize = 0;
0799:                }
0800:                // resolves previous forward references to label, if any
0801:                resize |= label.resolve(this , code.length, code.data);
0802:            }
0803:
0804:            public void visitLdcInsn(final Object cst) {
0805:                Item i = cw.newCst(cst);
0806:                if (computeMaxs) {
0807:                    int size;
0808:                    // computes the stack size variation
0809:                    if (i.type == ClassWriter.LONG
0810:                            || i.type == ClassWriter.DOUBLE) {
0811:                        size = stackSize + 2;
0812:                    } else {
0813:                        size = stackSize + 1;
0814:                    }
0815:                    // updates current and max stack sizes
0816:                    if (size > maxStackSize) {
0817:                        maxStackSize = size;
0818:                    }
0819:                    stackSize = size;
0820:                }
0821:                // adds the instruction to the bytecode of the method
0822:                int index = i.index;
0823:                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
0824:                    code.put12(20 /*LDC2_W*/, index);
0825:                } else if (index >= 256) {
0826:                    code.put12(19 /*LDC_W*/, index);
0827:                } else {
0828:                    code.put11(Constants.LDC, index);
0829:                }
0830:            }
0831:
0832:            public void visitIincInsn(final int var, final int increment) {
0833:                if (computeMaxs) {
0834:                    // updates max locals only (no stack change)
0835:                    int n = var + 1;
0836:                    if (n > maxLocals) {
0837:                        maxLocals = n;
0838:                    }
0839:                }
0840:                // adds the instruction to the bytecode of the method
0841:                if ((var > 255) || (increment > 127) || (increment < -128)) {
0842:                    code.put1(196 /*WIDE*/).put12(Constants.IINC, var).put2(
0843:                            increment);
0844:                } else {
0845:                    code.put1(Constants.IINC).put11(var, increment);
0846:                }
0847:            }
0848:
0849:            public void visitTableSwitchInsn(final int min, final int max,
0850:                    final Label dflt, final Label labels[]) {
0851:                if (computeMaxs) {
0852:                    // updates current stack size (max stack size unchanged)
0853:                    --stackSize;
0854:                    // ends current block (with many new successors)
0855:                    if (currentBlock != null) {
0856:                        currentBlock.maxStackSize = maxStackSize;
0857:                        addSuccessor(stackSize, dflt);
0858:                        for (int i = 0; i < labels.length; ++i) {
0859:                            addSuccessor(stackSize, labels[i]);
0860:                        }
0861:                        currentBlock = null;
0862:                    }
0863:                }
0864:                // adds the instruction to the bytecode of the method
0865:                int source = code.length;
0866:                code.put1(Constants.TABLESWITCH);
0867:                while (code.length % 4 != 0) {
0868:                    code.put1(0);
0869:                }
0870:                dflt.put(this , code, source, true);
0871:                code.put4(min).put4(max);
0872:                for (int i = 0; i < labels.length; ++i) {
0873:                    labels[i].put(this , code, source, true);
0874:                }
0875:            }
0876:
0877:            public void visitLookupSwitchInsn(final Label dflt,
0878:                    final int keys[], final Label labels[]) {
0879:                if (computeMaxs) {
0880:                    // updates current stack size (max stack size unchanged)
0881:                    --stackSize;
0882:                    // ends current block (with many new successors)
0883:                    if (currentBlock != null) {
0884:                        currentBlock.maxStackSize = maxStackSize;
0885:                        addSuccessor(stackSize, dflt);
0886:                        for (int i = 0; i < labels.length; ++i) {
0887:                            addSuccessor(stackSize, labels[i]);
0888:                        }
0889:                        currentBlock = null;
0890:                    }
0891:                }
0892:                // adds the instruction to the bytecode of the method
0893:                int source = code.length;
0894:                code.put1(Constants.LOOKUPSWITCH);
0895:                while (code.length % 4 != 0) {
0896:                    code.put1(0);
0897:                }
0898:                dflt.put(this , code, source, true);
0899:                code.put4(labels.length);
0900:                for (int i = 0; i < labels.length; ++i) {
0901:                    code.put4(keys[i]);
0902:                    labels[i].put(this , code, source, true);
0903:                }
0904:            }
0905:
0906:            public void visitMultiANewArrayInsn(final String desc,
0907:                    final int dims) {
0908:                if (computeMaxs) {
0909:                    // updates current stack size (max stack size unchanged because stack
0910:                    // size variation always negative or null)
0911:                    stackSize += 1 - dims;
0912:                }
0913:                // adds the instruction to the bytecode of the method
0914:                Item classItem = cw.newClass(desc);
0915:                code.put12(Constants.MULTIANEWARRAY, classItem.index)
0916:                        .put1(dims);
0917:            }
0918:
0919:            public void visitTryCatchBlock(final Label start, final Label end,
0920:                    final Label handler, final String type) {
0921:                if (CHECK) {
0922:                    if (start.owner != this  || end.owner != this 
0923:                            || handler.owner != this ) {
0924:                        throw new IllegalArgumentException();
0925:                    }
0926:                    if (!start.resolved || !end.resolved || !handler.resolved) {
0927:                        throw new IllegalArgumentException();
0928:                    }
0929:                }
0930:                if (computeMaxs) {
0931:                    // pushes handler block onto the stack of blocks to be visited
0932:                    if (!handler.pushed) {
0933:                        handler.beginStackSize = 1;
0934:                        handler.pushed = true;
0935:                        handler.next = blockStack;
0936:                        blockStack = handler;
0937:                    }
0938:                }
0939:                ++catchCount;
0940:                if (catchTable == null) {
0941:                    catchTable = new ByteVector();
0942:                }
0943:                catchTable.put2(start.position);
0944:                catchTable.put2(end.position);
0945:                catchTable.put2(handler.position);
0946:                catchTable.put2(type != null ? cw.newClass(type).index : 0);
0947:            }
0948:
0949:            public void visitMaxs(final int maxStack, final int maxLocals) {
0950:                if (computeMaxs) {
0951:                    // true (non relative) max stack size
0952:                    int max = 0;
0953:                    // control flow analysis algorithm: while the block stack is not empty,
0954:                    // pop a block from this stack, update the max stack size, compute
0955:                    // the true (non relative) begin stack size of the successors of this
0956:                    // block, and push these successors onto the stack (unless they have
0957:                    // already been pushed onto the stack). Note: by hypothesis, the {@link
0958:                    // Label#beginStackSize} of the blocks in the block stack are the true
0959:                    // (non relative) beginning stack sizes of these blocks.
0960:                    Label stack = blockStack;
0961:                    while (stack != null) {
0962:                        // pops a block from the stack
0963:                        Label l = stack;
0964:                        stack = stack.next;
0965:                        // computes the true (non relative) max stack size of this block
0966:                        int start = l.beginStackSize;
0967:                        int blockMax = start + l.maxStackSize;
0968:                        // updates the global max stack size
0969:                        if (blockMax > max) {
0970:                            max = blockMax;
0971:                        }
0972:                        // analyses the successors of the block
0973:                        Edge b = l.successors;
0974:                        while (b != null) {
0975:                            l = b.successor;
0976:                            // if this successor has not already been pushed onto the stack...
0977:                            if (!l.pushed) {
0978:                                // computes the true beginning stack size of this successor block
0979:                                l.beginStackSize = start + b.stackSize;
0980:                                // pushes this successor onto the stack
0981:                                l.pushed = true;
0982:                                l.next = stack;
0983:                                stack = l;
0984:                            }
0985:                            b = b.next;
0986:                        }
0987:                    }
0988:                    this .maxStack = max;
0989:                    // releases all the Edge objects used by this CodeWriter
0990:                    synchronized (SIZE) {
0991:                        // appends the [head ... tail] list at the beginning of the pool list
0992:                        if (tail != null) {
0993:                            tail.poolNext = pool;
0994:                            pool = head;
0995:                        }
0996:                    }
0997:                } else {
0998:                    this .maxStack = maxStack;
0999:                    this .maxLocals = maxLocals;
1000:                }
1001:            }
1002:
1003:            public void visitLocalVariable(final String name,
1004:                    final String desc, final Label start, final Label end,
1005:                    final int index) {
1006:                if (CHECK) {
1007:                    if (start.owner != this  || !start.resolved) {
1008:                        throw new IllegalArgumentException();
1009:                    }
1010:                    if (end.owner != this  || !end.resolved) {
1011:                        throw new IllegalArgumentException();
1012:                    }
1013:                }
1014:                if (localVar == null) {
1015:                    cw.newUTF8("LocalVariableTable");
1016:                    localVar = new ByteVector();
1017:                }
1018:                ++localVarCount;
1019:                localVar.put2(start.position);
1020:                localVar.put2(end.position - start.position);
1021:                localVar.put2(cw.newUTF8(name).index);
1022:                localVar.put2(cw.newUTF8(desc).index);
1023:                localVar.put2(index);
1024:            }
1025:
1026:            public void visitLineNumber(final int line, final Label start) {
1027:                if (CHECK) {
1028:                    if (start.owner != this  || !start.resolved) {
1029:                        throw new IllegalArgumentException();
1030:                    }
1031:                }
1032:                if (lineNumber == null) {
1033:                    cw.newUTF8("LineNumberTable");
1034:                    lineNumber = new ByteVector();
1035:                }
1036:                ++lineNumberCount;
1037:                lineNumber.put2(start.position);
1038:                lineNumber.put2(line);
1039:            }
1040:
1041:            // --------------------------------------------------------------------------
1042:            // Utility methods: control flow analysis algorithm
1043:            // --------------------------------------------------------------------------
1044:
1045:            /**
1046:             * Computes the size of the arguments and of the return value of a method.
1047:             *
1048:             * @param desc the descriptor of a method.
1049:             * @return the size of the arguments of the method (plus one for the implicit
1050:             *      this argument), argSize, and the size of its return value, retSize,
1051:             *      packed into a single int i = <tt>(argSize << 2) | retSize</tt>
1052:             *      (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
1053:             *      <tt>i & 0x03</tt>).
1054:             */
1055:
1056:            private static int getArgumentsAndReturnSizes(final String desc) {
1057:                int n = 1;
1058:                int c = 1;
1059:                while (true) {
1060:                    char car = desc.charAt(c++);
1061:                    if (car == ')') {
1062:                        car = desc.charAt(c);
1063:                        return n << 2
1064:                                | (car == 'V' ? 0
1065:                                        : (car == 'D' || car == 'J' ? 2 : 1));
1066:                    } else if (car == 'L') {
1067:                        while (desc.charAt(c++) != ';') {
1068:                        }
1069:                        n += 1;
1070:                    } else if (car == '[') {
1071:                        while ((car = desc.charAt(c)) == '[') {
1072:                            ++c;
1073:                        }
1074:                        if (car == 'D' || car == 'J') {
1075:                            n -= 1;
1076:                        }
1077:                    } else if (car == 'D' || car == 'J') {
1078:                        n += 2;
1079:                    } else {
1080:                        n += 1;
1081:                    }
1082:                }
1083:            }
1084:
1085:            /**
1086:             * Adds a successor to the {@link #currentBlock currentBlock} block.
1087:             *
1088:             * @param stackSize the current (relative) stack size in the current block.
1089:             * @param successor the successor block to be added to the current block.
1090:             */
1091:
1092:            private void addSuccessor(final int stackSize, final Label successor) {
1093:                Edge b;
1094:                // creates a new Edge object or reuses one from the shared pool
1095:                synchronized (SIZE) {
1096:                    if (pool == null) {
1097:                        b = new Edge();
1098:                    } else {
1099:                        b = pool;
1100:                        // removes b from the pool
1101:                        pool = pool.poolNext;
1102:                    }
1103:                }
1104:                // adds the previous Edge to the list of Edges used by this CodeWriter
1105:                if (tail == null) {
1106:                    tail = b;
1107:                }
1108:                b.poolNext = head;
1109:                head = b;
1110:                // initializes the previous Edge object...
1111:                b.stackSize = stackSize;
1112:                b.successor = successor;
1113:                // ...and adds it to the successor list of the currentBlock block
1114:                b.next = currentBlock.successors;
1115:                currentBlock.successors = b;
1116:            }
1117:
1118:            // --------------------------------------------------------------------------
1119:            // Utility methods: dump bytecode array
1120:            // --------------------------------------------------------------------------
1121:
1122:            /**
1123:             * Returns the size of the bytecode of this method.
1124:             *
1125:             * @return the size of the bytecode of this method.
1126:             */
1127:
1128:            final int getSize() {
1129:                if (resize) {
1130:                    // replaces the temporary jump opcodes introduced by Label.resolve.
1131:                    resizeInstructions(new int[0], new int[0], 0);
1132:                }
1133:                int size = 8;
1134:                if (code.length > 0) {
1135:                    cw.newUTF8("Code");
1136:                    size += 18 + code.length + 8 * catchCount;
1137:                    if (localVar != null) {
1138:                        size += 8 + localVar.length;
1139:                    }
1140:                    if (lineNumber != null) {
1141:                        size += 8 + lineNumber.length;
1142:                    }
1143:                }
1144:                if (exceptionCount > 0) {
1145:                    cw.newUTF8("Exceptions");
1146:                    size += 8 + 2 * exceptionCount;
1147:                }
1148:                if ((access & Constants.ACC_SYNTHETIC) != 0) {
1149:                    cw.newUTF8("Synthetic");
1150:                    size += 6;
1151:                }
1152:                if ((access & Constants.ACC_DEPRECATED) != 0) {
1153:                    cw.newUTF8("Deprecated");
1154:                    size += 6;
1155:                }
1156:                return size;
1157:            }
1158:
1159:            /**
1160:             * Puts the bytecode of this method in the given byte vector.
1161:             *
1162:             * @param out the byte vector into which the bytecode of this method must be
1163:             *      copied.
1164:             */
1165:
1166:            final void put(final ByteVector out) {
1167:                out.put2(access).put2(name.index).put2(desc.index);
1168:                int attributeCount = 0;
1169:                if (code.length > 0) {
1170:                    ++attributeCount;
1171:                }
1172:                if (exceptionCount > 0) {
1173:                    ++attributeCount;
1174:                }
1175:                if ((access & Constants.ACC_SYNTHETIC) != 0) {
1176:                    ++attributeCount;
1177:                }
1178:                if ((access & Constants.ACC_DEPRECATED) != 0) {
1179:                    ++attributeCount;
1180:                }
1181:                out.put2(attributeCount);
1182:                if (code.length > 0) {
1183:                    int size = 12 + code.length + 8 * catchCount;
1184:                    if (localVar != null) {
1185:                        size += 8 + localVar.length;
1186:                    }
1187:                    if (lineNumber != null) {
1188:                        size += 8 + lineNumber.length;
1189:                    }
1190:                    out.put2(cw.newUTF8("Code").index).put4(size);
1191:                    out.put2(maxStack).put2(maxLocals);
1192:                    out.put4(code.length).putByteArray(code.data, 0,
1193:                            code.length);
1194:                    out.put2(catchCount);
1195:                    if (catchCount > 0) {
1196:                        out.putByteArray(catchTable.data, 0, catchTable.length);
1197:                    }
1198:                    attributeCount = 0;
1199:                    if (localVar != null) {
1200:                        ++attributeCount;
1201:                    }
1202:                    if (lineNumber != null) {
1203:                        ++attributeCount;
1204:                    }
1205:                    out.put2(attributeCount);
1206:                    if (localVar != null) {
1207:                        out.put2(cw.newUTF8("LocalVariableTable").index);
1208:                        out.put4(localVar.length + 2).put2(localVarCount);
1209:                        out.putByteArray(localVar.data, 0, localVar.length);
1210:                    }
1211:                    if (lineNumber != null) {
1212:                        out.put2(cw.newUTF8("LineNumberTable").index);
1213:                        out.put4(lineNumber.length + 2).put2(lineNumberCount);
1214:                        out.putByteArray(lineNumber.data, 0, lineNumber.length);
1215:                    }
1216:                }
1217:                if (exceptionCount > 0) {
1218:                    out.put2(cw.newUTF8("Exceptions").index).put4(
1219:                            2 * exceptionCount + 2);
1220:                    out.put2(exceptionCount);
1221:                    for (int i = 0; i < exceptionCount; ++i) {
1222:                        out.put2(exceptions[i]);
1223:                    }
1224:                }
1225:                if ((access & Constants.ACC_SYNTHETIC) != 0) {
1226:                    out.put2(cw.newUTF8("Synthetic").index).put4(0);
1227:                }
1228:                if ((access & Constants.ACC_DEPRECATED) != 0) {
1229:                    out.put2(cw.newUTF8("Deprecated").index).put4(0);
1230:                }
1231:            }
1232:
1233:            // --------------------------------------------------------------------------
1234:            // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
1235:            // --------------------------------------------------------------------------
1236:
1237:            /**
1238:             * Resizes the designated instructions, while keeping jump offsets and
1239:             * instruction addresses consistent. This may require to resize other existing
1240:             * instructions, or even to introduce new instructions: for example,
1241:             * increasing the size of an instruction by 2 at the middle of a method can
1242:             * increases the offset of an IFEQ instruction from 32766 to 32768, in which
1243:             * case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W 32765. This, in turn,
1244:             * may require to increase the size of another jump instruction, and so on...
1245:             * All these operations are handled automatically by this method.
1246:             * <p>
1247:             * <i>This method must be called after all the method that is being built has
1248:             * been visited</i>. In particular, the {@link Label Label} objects used to
1249:             * construct the method are no longer valid after this method has been called.
1250:             *
1251:             * @param indexes current positions of the instructions to be resized. Each
1252:             *      instruction must be designated by the index of its <i>last</i> byte,
1253:             *      plus one (or, in other words, by the index of the <i>first</i> byte of
1254:             *      the <i>next</i> instruction).
1255:             * @param sizes the number of bytes to be <i>added</i> to the above
1256:             *      instructions. More precisely, for each i &lt; <tt>len</tt>,
1257:             *      <tt>sizes</tt>[i] bytes will be added at the end of the instruction
1258:             *      designated by <tt>indexes</tt>[i] or, if <tt>sizes</tt>[i] is
1259:             *      negative, the <i>last</i> |<tt>sizes[i]</tt>| bytes of the instruction
1260:             *      will be removed (the instruction size <i>must not</i> become negative
1261:             *      or null). The gaps introduced by this method must be filled in
1262:             *      "manually" in the array returned by the {@link #getCode getCode}
1263:             *      method.
1264:             * @param len the number of instruction to be resized. Must be smaller than or
1265:             *      equal to <tt>indexes</tt>.length and <tt>sizes</tt>.length.
1266:             * @return the <tt>indexes</tt> array, which now contains the new positions of
1267:             *      the resized instructions (designated as above).
1268:             */
1269:
1270:            protected int[] resizeInstructions(final int[] indexes,
1271:                    final int[] sizes, final int len) {
1272:                byte[] b = code.data; // bytecode of the method
1273:                int u, v, label; // indexes in b
1274:                int i, j; // loop indexes
1275:
1276:                // 1st step:
1277:                // As explained above, resizing an instruction may require to resize another
1278:                // one, which may require to resize yet another one, and so on. The first
1279:                // step of the algorithm consists in finding all the instructions that
1280:                // need to be resized, without modifying the code. This is done by the
1281:                // following "fix point" algorithm:
1282:                // - parse the code to find the jump instructions whose offset will need
1283:                //   more than 2 bytes to be stored (the future offset is computed from the
1284:                //   current offset and from the number of bytes that will be inserted or
1285:                //   removed between the source and target instructions). For each such
1286:                //   instruction, adds an entry in (a copy of) the indexes and sizes arrays
1287:                //   (if this has not already been done in a previous iteration!)
1288:                // - if at least one entry has been added during the previous step, go back
1289:                //   to the beginning, otherwise stop.
1290:                // In fact the real algorithm is complicated by the fact that the size of
1291:                // TABLESWITCH and LOOKUPSWITCH instructions depends on their position in
1292:                // the bytecode (because of padding). In order to ensure the convergence of
1293:                // the algorithm, the number of bytes to be added or removed from these
1294:                // instructions is over estimated during the previous loop, and computed
1295:                // exactly only after the loop is finished (this requires another pass to
1296:                // parse the bytecode of the method).
1297:
1298:                int[] allIndexes = new int[len]; // copy of indexes
1299:                int[] allSizes = new int[len]; // copy of sizes
1300:                boolean[] resize; // instructions to be resized
1301:                int newOffset; // future offset of a jump instruction
1302:
1303:                System.arraycopy(indexes, 0, allIndexes, 0, len);
1304:                System.arraycopy(sizes, 0, allSizes, 0, len);
1305:                resize = new boolean[code.length];
1306:
1307:                int state = 3; // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
1308:                do {
1309:                    if (state == 3) {
1310:                        state = 2;
1311:                    }
1312:                    u = 0;
1313:                    while (u < b.length) {
1314:                        int opcode = b[u] & 0xFF; // opcode of current instruction
1315:                        int insert = 0; // bytes to be added after this instruction
1316:
1317:                        switch (ClassWriter.TYPE[opcode]) {
1318:                        case ClassWriter.NOARG_INSN:
1319:                        case ClassWriter.IMPLVAR_INSN:
1320:                            u += 1;
1321:                            break;
1322:                        case ClassWriter.LABEL_INSN:
1323:                            if (opcode > 201) {
1324:                                // converts temporary opcodes 202 to 217 (inclusive), 218 and 219
1325:                                // to IFEQ ... JSR (inclusive), IFNULL and IFNONNULL
1326:                                opcode = opcode < 218 ? opcode - 49
1327:                                        : opcode - 20;
1328:                                label = u + readUnsignedShort(b, u + 1);
1329:                            } else {
1330:                                label = u + readShort(b, u + 1);
1331:                            }
1332:                            newOffset = getNewOffset(allIndexes, allSizes, u,
1333:                                    label);
1334:                            if (newOffset < Short.MIN_VALUE
1335:                                    || newOffset > Short.MAX_VALUE) {
1336:                                if (!resize[u]) {
1337:                                    if (opcode == Constants.GOTO
1338:                                            || opcode == Constants.JSR) {
1339:                                        // two additional bytes will be required to replace this
1340:                                        // GOTO or JSR instruction with a GOTO_W or a JSR_W
1341:                                        insert = 2;
1342:                                    } else {
1343:                                        // five additional bytes will be required to replace this
1344:                                        // IFxxx <l> instruction with IFNOTxxx <l'> GOTO_W <l>, where
1345:                                        // IFNOTxxx is the "opposite" opcode of IFxxx (i.e., IFNE for
1346:                                        // IFEQ) and where <l'> designates the instruction just after
1347:                                        // the GOTO_W.
1348:                                        insert = 5;
1349:                                    }
1350:                                    resize[u] = true;
1351:                                }
1352:                            }
1353:                            u += 3;
1354:                            break;
1355:                        case ClassWriter.LABELW_INSN:
1356:                            u += 5;
1357:                            break;
1358:                        case ClassWriter.TABL_INSN:
1359:                            if (state == 1) {
1360:                                // true number of bytes to be added (or removed) from this
1361:                                // instruction = (future number of padding bytes - current number
1362:                                // of padding byte) - previously over estimated variation =
1363:                                // = ((3 - newOffset%4) - (3 - u%4)) - u%4
1364:                                // = (-newOffset%4 + u%4) - u%4
1365:                                // = -(newOffset & 3)
1366:                                newOffset = getNewOffset(allIndexes, allSizes,
1367:                                        0, u);
1368:                                insert = -(newOffset & 3);
1369:                            } else if (!resize[u]) {
1370:                                // over estimation of the number of bytes to be added to this
1371:                                // instruction = 3 - current number of padding bytes = 3 - (3 -
1372:                                // u%4) = u%4 = u & 3
1373:                                insert = u & 3;
1374:                                resize[u] = true;
1375:                            }
1376:                            // skips instruction
1377:                            u = u + 4 - (u & 3);
1378:                            u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
1379:                            break;
1380:                        case ClassWriter.LOOK_INSN:
1381:                            if (state == 1) {
1382:                                // like TABL_INSN
1383:                                newOffset = getNewOffset(allIndexes, allSizes,
1384:                                        0, u);
1385:                                insert = -(newOffset & 3);
1386:                            } else if (!resize[u]) {
1387:                                // like TABL_INSN
1388:                                insert = u & 3;
1389:                                resize[u] = true;
1390:                            }
1391:                            // skips instruction
1392:                            u = u + 4 - (u & 3);
1393:                            u += 8 * readInt(b, u + 4) + 8;
1394:                            break;
1395:                        case ClassWriter.WIDE_INSN:
1396:                            opcode = b[u + 1] & 0xFF;
1397:                            if (opcode == Constants.IINC) {
1398:                                u += 6;
1399:                            } else {
1400:                                u += 4;
1401:                            }
1402:                            break;
1403:                        case ClassWriter.VAR_INSN:
1404:                        case ClassWriter.SBYTE_INSN:
1405:                        case ClassWriter.LDC_INSN:
1406:                            u += 2;
1407:                            break;
1408:                        case ClassWriter.SHORT_INSN:
1409:                        case ClassWriter.LDCW_INSN:
1410:                        case ClassWriter.FIELDORMETH_INSN:
1411:                        case ClassWriter.TYPE_INSN:
1412:                        case ClassWriter.IINC_INSN:
1413:                            u += 3;
1414:                            break;
1415:                        case ClassWriter.ITFMETH_INSN:
1416:                            u += 5;
1417:                            break;
1418:                        // case ClassWriter.MANA_INSN:
1419:                        default:
1420:                            u += 4;
1421:                            break;
1422:                        }
1423:                        if (insert != 0) {
1424:                            // adds a new (u, insert) entry in the allIndexes and allSizes arrays
1425:                            int[] newIndexes = new int[allIndexes.length + 1];
1426:                            int[] newSizes = new int[allSizes.length + 1];
1427:                            System.arraycopy(allIndexes, 0, newIndexes, 0,
1428:                                    allIndexes.length);
1429:                            System.arraycopy(allSizes, 0, newSizes, 0,
1430:                                    allSizes.length);
1431:                            newIndexes[allIndexes.length] = u;
1432:                            newSizes[allSizes.length] = insert;
1433:                            allIndexes = newIndexes;
1434:                            allSizes = newSizes;
1435:                            if (insert > 0) {
1436:                                state = 3;
1437:                            }
1438:                        }
1439:                    }
1440:                    if (state < 3) {
1441:                        --state;
1442:                    }
1443:                } while (state != 0);
1444:
1445:                // 2nd step:
1446:                // copies the bytecode of the method into a new bytevector, updates the
1447:                // offsets, and inserts (or removes) bytes as requested.
1448:
1449:                ByteVector newCode = new ByteVector(code.length);
1450:
1451:                u = 0;
1452:                while (u < code.length) {
1453:                    for (i = allIndexes.length - 1; i >= 0; --i) {
1454:                        if (allIndexes[i] == u) {
1455:                            if (i < len) {
1456:                                if (sizes[i] > 0) {
1457:                                    newCode.putByteArray(null, 0, sizes[i]);
1458:                                } else {
1459:                                    newCode.length += sizes[i];
1460:                                }
1461:                                indexes[i] = newCode.length;
1462:                            }
1463:                        }
1464:                    }
1465:                    int opcode = b[u] & 0xFF;
1466:                    switch (ClassWriter.TYPE[opcode]) {
1467:                    case ClassWriter.NOARG_INSN:
1468:                    case ClassWriter.IMPLVAR_INSN:
1469:                        newCode.put1(opcode);
1470:                        u += 1;
1471:                        break;
1472:                    case ClassWriter.LABEL_INSN:
1473:                        if (opcode > 201) {
1474:                            // changes temporary opcodes 202 to 217 (inclusive), 218 and 219
1475:                            // to IFEQ ... JSR (inclusive), IFNULL and IFNONNULL
1476:                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;
1477:                            label = u + readUnsignedShort(b, u + 1);
1478:                        } else {
1479:                            label = u + readShort(b, u + 1);
1480:                        }
1481:                        newOffset = getNewOffset(allIndexes, allSizes, u, label);
1482:                        if (newOffset < Short.MIN_VALUE
1483:                                || newOffset > Short.MAX_VALUE) {
1484:                            // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx <l> with
1485:                            // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the "opposite" opcode
1486:                            // of IFxxx (i.e., IFNE for IFEQ) and where <l'> designates the
1487:                            // instruction just after the GOTO_W.
1488:                            if (opcode == Constants.GOTO) {
1489:                                newCode.put1(200); // GOTO_W
1490:                            } else if (opcode == Constants.JSR) {
1491:                                newCode.put1(201); // JSR_W
1492:                            } else {
1493:                                newCode
1494:                                        .put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
1495:                                                : opcode ^ 1);
1496:                                newCode.put2(8); // jump offset
1497:                                newCode.put1(200); // GOTO_W
1498:                                newOffset -= 3; // newOffset now computed from start of GOTO_W
1499:                            }
1500:                            newCode.put4(newOffset);
1501:                        } else {
1502:                            newCode.put1(opcode);
1503:                            newCode.put2(newOffset);
1504:                        }
1505:                        u += 3;
1506:                        break;
1507:                    case ClassWriter.LABELW_INSN:
1508:                        label = u + readInt(b, u + 1);
1509:                        newOffset = getNewOffset(allIndexes, allSizes, u, label);
1510:                        newCode.put1(opcode);
1511:                        newCode.put4(newOffset);
1512:                        u += 5;
1513:                        break;
1514:                    case ClassWriter.TABL_INSN:
1515:                        // skips 0 to 3 padding bytes
1516:                        v = u;
1517:                        u = u + 4 - (v & 3);
1518:                        // reads and copies instruction
1519:                        int source = newCode.length;
1520:                        newCode.put1(Constants.TABLESWITCH);
1521:                        while (newCode.length % 4 != 0) {
1522:                            newCode.put1(0);
1523:                        }
1524:                        label = v + readInt(b, u);
1525:                        u += 4;
1526:                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
1527:                        newCode.put4(newOffset);
1528:                        j = readInt(b, u);
1529:                        u += 4;
1530:                        newCode.put4(j);
1531:                        j = readInt(b, u) - j + 1;
1532:                        u += 4;
1533:                        newCode.put4(readInt(b, u - 4));
1534:                        for (; j > 0; --j) {
1535:                            label = v + readInt(b, u);
1536:                            u += 4;
1537:                            newOffset = getNewOffset(allIndexes, allSizes, v,
1538:                                    label);
1539:                            newCode.put4(newOffset);
1540:                        }
1541:                        break;
1542:                    case ClassWriter.LOOK_INSN:
1543:                        // skips 0 to 3 padding bytes
1544:                        v = u;
1545:                        u = u + 4 - (v & 3);
1546:                        // reads and copies instruction
1547:                        source = newCode.length;
1548:                        newCode.put1(Constants.LOOKUPSWITCH);
1549:                        while (newCode.length % 4 != 0) {
1550:                            newCode.put1(0);
1551:                        }
1552:                        label = v + readInt(b, u);
1553:                        u += 4;
1554:                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
1555:                        newCode.put4(newOffset);
1556:                        j = readInt(b, u);
1557:                        u += 4;
1558:                        newCode.put4(j);
1559:                        for (; j > 0; --j) {
1560:                            newCode.put4(readInt(b, u));
1561:                            u += 4;
1562:                            label = v + readInt(b, u);
1563:                            u += 4;
1564:                            newOffset = getNewOffset(allIndexes, allSizes, v,
1565:                                    label);
1566:                            newCode.put4(newOffset);
1567:                        }
1568:                        break;
1569:                    case ClassWriter.WIDE_INSN:
1570:                        opcode = b[u + 1] & 0xFF;
1571:                        if (opcode == Constants.IINC) {
1572:                            newCode.putByteArray(b, u, 6);
1573:                            u += 6;
1574:                        } else {
1575:                            newCode.putByteArray(b, u, 4);
1576:                            u += 4;
1577:                        }
1578:                        break;
1579:                    case ClassWriter.VAR_INSN:
1580:                    case ClassWriter.SBYTE_INSN:
1581:                    case ClassWriter.LDC_INSN:
1582:                        newCode.putByteArray(b, u, 2);
1583:                        u += 2;
1584:                        break;
1585:                    case ClassWriter.SHORT_INSN:
1586:                    case ClassWriter.LDCW_INSN:
1587:                    case ClassWriter.FIELDORMETH_INSN:
1588:                    case ClassWriter.TYPE_INSN:
1589:                    case ClassWriter.IINC_INSN:
1590:                        newCode.putByteArray(b, u, 3);
1591:                        u += 3;
1592:                        break;
1593:                    case ClassWriter.ITFMETH_INSN:
1594:                        newCode.putByteArray(b, u, 5);
1595:                        u += 5;
1596:                        break;
1597:                    // case MANA_INSN:
1598:                    default:
1599:                        newCode.putByteArray(b, u, 4);
1600:                        u += 4;
1601:                        break;
1602:                    }
1603:                }
1604:
1605:                // updates the instructions addresses in the
1606:                // catch, local var and line number tables
1607:                if (catchTable != null) {
1608:                    b = catchTable.data;
1609:                    u = 0;
1610:                    while (u < catchTable.length) {
1611:                        writeShort(b, u, getNewOffset(allIndexes, allSizes, 0,
1612:                                readUnsignedShort(b, u)));
1613:                        writeShort(b, u + 2, getNewOffset(allIndexes, allSizes,
1614:                                0, readUnsignedShort(b, u + 2)));
1615:                        writeShort(b, u + 4, getNewOffset(allIndexes, allSizes,
1616:                                0, readUnsignedShort(b, u + 4)));
1617:                        u += 8;
1618:                    }
1619:                }
1620:                if (localVar != null) {
1621:                    b = localVar.data;
1622:                    u = 0;
1623:                    while (u < localVar.length) {
1624:                        label = readUnsignedShort(b, u);
1625:                        newOffset = getNewOffset(allIndexes, allSizes, 0, label);
1626:                        writeShort(b, u, newOffset);
1627:                        label += readUnsignedShort(b, u + 2);
1628:                        newOffset = getNewOffset(allIndexes, allSizes, 0, label)
1629:                                - newOffset;
1630:                        writeShort(b, u, newOffset);
1631:                        u += 10;
1632:                    }
1633:                }
1634:                if (lineNumber != null) {
1635:                    b = lineNumber.data;
1636:                    u = 0;
1637:                    while (u < lineNumber.length) {
1638:                        writeShort(b, u, getNewOffset(allIndexes, allSizes, 0,
1639:                                readUnsignedShort(b, u)));
1640:                        u += 4;
1641:                    }
1642:                }
1643:
1644:                // replaces old bytecodes with new ones
1645:                code = newCode;
1646:
1647:                // returns the positions of the resized instructions
1648:                return indexes;
1649:            }
1650:
1651:            /**
1652:             * Reads an unsigned short value in the given byte array.
1653:             *
1654:             * @param b a byte array.
1655:             * @param index the start index of the value to be read.
1656:             * @return the read value.
1657:             */
1658:
1659:            static int readUnsignedShort(final byte[] b, final int index) {
1660:                return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1661:            }
1662:
1663:            /**
1664:             * Reads a signed short value in the given byte array.
1665:             *
1666:             * @param b a byte array.
1667:             * @param index the start index of the value to be read.
1668:             * @return the read value.
1669:             */
1670:
1671:            static short readShort(final byte[] b, final int index) {
1672:                return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1673:            }
1674:
1675:            /**
1676:             * Reads a signed int value in the given byte array.
1677:             *
1678:             * @param b a byte array.
1679:             * @param index the start index of the value to be read.
1680:             * @return the read value.
1681:             */
1682:
1683:            static int readInt(final byte[] b, final int index) {
1684:                return ((b[index] & 0xFF) << 24)
1685:                        | ((b[index + 1] & 0xFF) << 16)
1686:                        | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1687:            }
1688:
1689:            /**
1690:             * Writes a short value in the given byte array.
1691:             *
1692:             * @param b a byte array.
1693:             * @param index where the first byte of the short value must be written.
1694:             * @param s the value to be written in the given byte array.
1695:             */
1696:
1697:            static void writeShort(final byte[] b, final int index, final int s) {
1698:                b[index] = (byte) (s >>> 8);
1699:                b[index + 1] = (byte) s;
1700:            }
1701:
1702:            /**
1703:             * Computes the future value of a bytecode offset.
1704:             * <p>
1705:             * Note: it is possible to have several entries for the same instruction
1706:             * in the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b)
1707:             * and (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').
1708:             *
1709:             * @param indexes current positions of the instructions to be resized. Each
1710:             *      instruction must be designated by the index of its <i>last</i> byte,
1711:             *      plus one (or, in other words, by the index of the <i>first</i> byte of
1712:             *      the <i>next</i> instruction).
1713:             * @param sizes the number of bytes to be <i>added</i> to the above
1714:             *      instructions. More precisely, for each i < <tt>len</tt>,
1715:             *      <tt>sizes</tt>[i] bytes will be added at the end of the instruction
1716:             *      designated by <tt>indexes</tt>[i] or, if <tt>sizes</tt>[i] is
1717:             *      negative, the <i>last</i> |<tt>sizes[i]</tt>| bytes of the instruction
1718:             *      will be removed (the instruction size <i>must not</i> become negative
1719:             *      or null).
1720:             * @param begin index of the first byte of the source instruction.
1721:             * @param end index of the first byte of the target instruction.
1722:             * @return the future value of the given bytecode offset.
1723:             */
1724:
1725:            static int getNewOffset(final int[] indexes, final int[] sizes,
1726:                    final int begin, final int end) {
1727:                int offset = end - begin;
1728:                for (int i = 0; i < indexes.length; ++i) {
1729:                    if (begin < indexes[i] && indexes[i] <= end) { // forward jump
1730:                        offset += sizes[i];
1731:                    } else if (end < indexes[i] && indexes[i] <= begin) { // backward jump
1732:                        offset -= sizes[i];
1733:                    }
1734:                }
1735:                return offset;
1736:            }
1737:
1738:            /**
1739:             * Returns the current size of the bytecode of this method. This size just
1740:             * includes the size of the bytecode instructions: it does not include the
1741:             * size of the Exceptions, LocalVariableTable, LineNumberTable, Synthetic
1742:             * and Deprecated attributes, if present.
1743:             *
1744:             * @return the current size of the bytecode of this method.
1745:             */
1746:
1747:            protected int getCodeSize() {
1748:                return code.length;
1749:            }
1750:
1751:            /**
1752:             * Returns the current bytecode of this method. This bytecode only contains
1753:             * the instructions: it does not include the Exceptions, LocalVariableTable,
1754:             * LineNumberTable, Synthetic and Deprecated attributes, if present.
1755:             *
1756:             * @return the current bytecode of this method. The bytecode is contained
1757:             *      between the index 0 (inclusive) and the index {@link #getCodeSize
1758:             *      getCodeSize} (exclusive).
1759:             */
1760:
1761:            protected byte[] getCode() {
1762:                return code.data;
1763:            }
1764:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.