Source Code Cross Referenced for Frame.java in  » Net » Terracotta » com » tc » 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 » Net » Terracotta » com.tc.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-2005 INRIA, France Telecom
0004:         * All rights reserved.
0005:         *
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions
0008:         * are met:
0009:         * 1. Redistributions of source code must retain the above copyright
0010:         *    notice, this list of conditions and the following disclaimer.
0011:         * 2. Redistributions in binary form must reproduce the above copyright
0012:         *    notice, this list of conditions and the following disclaimer in the
0013:         *    documentation and/or other materials provided with the distribution.
0014:         * 3. Neither the name of the copyright holders nor the names of its
0015:         *    contributors may be used to endorse or promote products derived from
0016:         *    this software without specific prior written permission.
0017:         *
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0028:         * THE POSSIBILITY OF SUCH DAMAGE.
0029:         */package com.tc.asm;
0030:
0031:        /**
0032:         * Information about the input and output stack map frames of a basic block.
0033:         * 
0034:         * @author Eric Bruneton
0035:         */
0036:        final class Frame {
0037:
0038:            /*
0039:             * Frames are computed in a two steps process: during the visit of each
0040:             * instruction, the state of the frame at the end of current basic block is
0041:             * updated by simulating the action of the instruction on the previous state
0042:             * of this so called "output frame". In visitMaxs, a fix point algorithm is
0043:             * used to compute the "input frame" of each basic block, i.e. the stack map
0044:             * frame at the begining of the basic block, starting from the input frame
0045:             * of the first basic block (which is computed from the method descriptor),
0046:             * and by using the previously computed output frames to compute the input
0047:             * state of the other blocks.
0048:             * 
0049:             * All output and input frames are stored as arrays of integers. Reference
0050:             * and array types are represented by an index into a type table (which is
0051:             * not the same as the constant pool of the class, in order to avoid adding
0052:             * unnecessary constants in the pool - not all computed frames will end up
0053:             * being stored in the stack map table). This allows very fast type
0054:             * comparisons.
0055:             * 
0056:             * Output stack map frames are computed relatively to the input frame of the
0057:             * basic block, which is not yet known when output frames are computed. It
0058:             * is therefore necessary to be able to represent abstract types such as
0059:             * "the type at position x in the input frame locals" or "the type at
0060:             * position x from the top of the input frame stack" or even "the type at
0061:             * position x in the input frame, with y more (or less) array dimensions".
0062:             * This explains the rather complicated type format used in output frames.
0063:             * 
0064:             * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
0065:             * signed number of array dimensions (from -8 to 7). KIND is either BASE,
0066:             * LOCAL or STACK. BASE is used for types that are not relative to the input
0067:             * frame. LOCAL is used for types that are relative to the input local
0068:             * variable types. STACK is used for types that are relative to the input
0069:             * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
0070:             * the input local variable types. For STACK types, it is a position
0071:             * relatively to the top of input frame stack. For BASE types, it is either
0072:             * one of the constants defined in FrameVisitor, or for OBJECT and
0073:             * UNINITIALIZED types, a tag and an index in the type table.
0074:             * 
0075:             * Output frames can contain types of any kind and with a positive or
0076:             * negative dimension (and even unassigned types, represented by 0 - which
0077:             * does not correspond to any valid type value). Input frames can only
0078:             * contain BASE types of positive or null dimension. In all cases the type
0079:             * table contains only internal type names (array type descriptors are
0080:             * forbidden - dimensions must be represented through the DIM field).
0081:             * 
0082:             * The LONG and DOUBLE types are always represented by using two slots (LONG +
0083:             * TOP or DOUBLE + TOP), for local variable types as well as in the operand
0084:             * stack. This is necessary to be able to simulate DUPx_y instructions,
0085:             * whose effect would be dependent on the actual type values if types were
0086:             * always represented by a single slot in the stack (and this is not
0087:             * possible, since actual type values are not always known - cf LOCAL and
0088:             * STACK type kinds).
0089:             */
0090:
0091:            /**
0092:             * Mask to get the dimension of a frame type. This dimension is a signed
0093:             * integer between -8 and 7.
0094:             */
0095:            final static int DIM = 0xF0000000;
0096:
0097:            /**
0098:             * Constant to be added to a type to get a type with one more dimension.
0099:             */
0100:            final static int ARRAY_OF = 0x10000000;
0101:
0102:            /**
0103:             * Constant to be added to a type to get a type with one less dimension.
0104:             */
0105:            final static int ELEMENT_OF = 0xF0000000;
0106:
0107:            /**
0108:             * Mask to get the kind of a frame type.
0109:             * 
0110:             * @see #BASE
0111:             * @see #LOCAL
0112:             * @see #STACK
0113:             */
0114:            final static int KIND = 0xF000000;
0115:
0116:            /**
0117:             * Mask to get the value of a frame type.
0118:             */
0119:            final static int VALUE = 0xFFFFFF;
0120:
0121:            /**
0122:             * Mask to get the kind of base types.
0123:             */
0124:            final static int BASE_KIND = 0xFF00000;
0125:
0126:            /**
0127:             * Mask to get the value of base types.
0128:             */
0129:            final static int BASE_VALUE = 0xFFFFF;
0130:
0131:            /**
0132:             * Kind of the types that are not relative to an input stack map frame.
0133:             */
0134:            final static int BASE = 0x1000000;
0135:
0136:            /**
0137:             * Base kind of the base reference types. The BASE_VALUE of such types is an
0138:             * index into the type table.
0139:             */
0140:            final static int OBJECT = BASE | 0x700000;
0141:
0142:            /**
0143:             * Base kind of the uninitialized base types. The BASE_VALUE of such types
0144:             * in an index into the type table (the Item at that index contains both an
0145:             * instruction offset and an internal class name).
0146:             */
0147:            final static int UNINITIALIZED = BASE | 0x800000;
0148:
0149:            /**
0150:             * Kind of the types that are relative to the local variable types of an
0151:             * input stack map frame. The value of such types is a local variable index.
0152:             */
0153:            private final static int LOCAL = 0x2000000;
0154:
0155:            /**
0156:             * Kind of the the types that are relative to the stack of an input stack
0157:             * map frame. The value of such types is a position relatively to the top of
0158:             * this stack.
0159:             */
0160:            private final static int STACK = 0x3000000;
0161:
0162:            /**
0163:             * The TOP type. This is a BASE type.
0164:             */
0165:            final static int TOP = BASE | 0;
0166:
0167:            /**
0168:             * The BOOLEAN type. This is a BASE type mainly used for array types.
0169:             */
0170:            final static int BOOLEAN = BASE | 9;
0171:
0172:            /**
0173:             * The BYTE type. This is a BASE type mainly used for array types.
0174:             */
0175:            final static int BYTE = BASE | 10;
0176:
0177:            /**
0178:             * The CHAR type. This is a BASE type mainly used for array types.
0179:             */
0180:            final static int CHAR = BASE | 11;
0181:
0182:            /**
0183:             * The SHORT type. This is a BASE type mainly used for array types.
0184:             */
0185:            final static int SHORT = BASE | 12;
0186:
0187:            /**
0188:             * The INTEGER type. This is a BASE type.
0189:             */
0190:            final static int INTEGER = BASE | 1;
0191:
0192:            /**
0193:             * The FLOAT type. This is a BASE type.
0194:             */
0195:            final static int FLOAT = BASE | 2;
0196:
0197:            /**
0198:             * The DOUBLE type. This is a BASE type.
0199:             */
0200:            final static int DOUBLE = BASE | 3;
0201:
0202:            /**
0203:             * The LONG type. This is a BASE type.
0204:             */
0205:            final static int LONG = BASE | 4;
0206:
0207:            /**
0208:             * The NULL type. This is a BASE type.
0209:             */
0210:            final static int NULL = BASE | 5;
0211:
0212:            /**
0213:             * The UNINITIALIZED_THIS type. This is a BASE type.
0214:             */
0215:            final static int UNINITIALIZED_THIS = BASE | 6;
0216:
0217:            /**
0218:             * The stack size variation corresponding to each JVM instruction. This
0219:             * stack variation is equal to the size of the values produced by an
0220:             * instruction, minus the size of the values consumed by this instruction.
0221:             */
0222:            final static int[] SIZE;
0223:
0224:            /**
0225:             * Computes the stack size variation corresponding to each JVM instruction.
0226:             */
0227:            static {
0228:                int i;
0229:                int[] b = new int[202];
0230:                String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
0231:                        + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
0232:                        + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
0233:                        + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
0234:                for (i = 0; i < b.length; ++i) {
0235:                    b[i] = s.charAt(i) - 'E';
0236:                }
0237:                SIZE = b;
0238:
0239:                // code to generate the above string
0240:                //
0241:                // int NA = 0; // not applicable (unused opcode or variable size opcode)
0242:                //
0243:                // b = new int[] {
0244:                // 0, //NOP, // visitInsn
0245:                // 1, //ACONST_NULL, // -
0246:                // 1, //ICONST_M1, // -
0247:                // 1, //ICONST_0, // -
0248:                // 1, //ICONST_1, // -
0249:                // 1, //ICONST_2, // -
0250:                // 1, //ICONST_3, // -
0251:                // 1, //ICONST_4, // -
0252:                // 1, //ICONST_5, // -
0253:                // 2, //LCONST_0, // -
0254:                // 2, //LCONST_1, // -
0255:                // 1, //FCONST_0, // -
0256:                // 1, //FCONST_1, // -
0257:                // 1, //FCONST_2, // -
0258:                // 2, //DCONST_0, // -
0259:                // 2, //DCONST_1, // -
0260:                // 1, //BIPUSH, // visitIntInsn
0261:                // 1, //SIPUSH, // -
0262:                // 1, //LDC, // visitLdcInsn
0263:                // NA, //LDC_W, // -
0264:                // NA, //LDC2_W, // -
0265:                // 1, //ILOAD, // visitVarInsn
0266:                // 2, //LLOAD, // -
0267:                // 1, //FLOAD, // -
0268:                // 2, //DLOAD, // -
0269:                // 1, //ALOAD, // -
0270:                // NA, //ILOAD_0, // -
0271:                // NA, //ILOAD_1, // -
0272:                // NA, //ILOAD_2, // -
0273:                // NA, //ILOAD_3, // -
0274:                // NA, //LLOAD_0, // -
0275:                // NA, //LLOAD_1, // -
0276:                // NA, //LLOAD_2, // -
0277:                // NA, //LLOAD_3, // -
0278:                // NA, //FLOAD_0, // -
0279:                // NA, //FLOAD_1, // -
0280:                // NA, //FLOAD_2, // -
0281:                // NA, //FLOAD_3, // -
0282:                // NA, //DLOAD_0, // -
0283:                // NA, //DLOAD_1, // -
0284:                // NA, //DLOAD_2, // -
0285:                // NA, //DLOAD_3, // -
0286:                // NA, //ALOAD_0, // -
0287:                // NA, //ALOAD_1, // -
0288:                // NA, //ALOAD_2, // -
0289:                // NA, //ALOAD_3, // -
0290:                // -1, //IALOAD, // visitInsn
0291:                // 0, //LALOAD, // -
0292:                // -1, //FALOAD, // -
0293:                // 0, //DALOAD, // -
0294:                // -1, //AALOAD, // -
0295:                // -1, //BALOAD, // -
0296:                // -1, //CALOAD, // -
0297:                // -1, //SALOAD, // -
0298:                // -1, //ISTORE, // visitVarInsn
0299:                // -2, //LSTORE, // -
0300:                // -1, //FSTORE, // -
0301:                // -2, //DSTORE, // -
0302:                // -1, //ASTORE, // -
0303:                // NA, //ISTORE_0, // -
0304:                // NA, //ISTORE_1, // -
0305:                // NA, //ISTORE_2, // -
0306:                // NA, //ISTORE_3, // -
0307:                // NA, //LSTORE_0, // -
0308:                // NA, //LSTORE_1, // -
0309:                // NA, //LSTORE_2, // -
0310:                // NA, //LSTORE_3, // -
0311:                // NA, //FSTORE_0, // -
0312:                // NA, //FSTORE_1, // -
0313:                // NA, //FSTORE_2, // -
0314:                // NA, //FSTORE_3, // -
0315:                // NA, //DSTORE_0, // -
0316:                // NA, //DSTORE_1, // -
0317:                // NA, //DSTORE_2, // -
0318:                // NA, //DSTORE_3, // -
0319:                // NA, //ASTORE_0, // -
0320:                // NA, //ASTORE_1, // -
0321:                // NA, //ASTORE_2, // -
0322:                // NA, //ASTORE_3, // -
0323:                // -3, //IASTORE, // visitInsn
0324:                // -4, //LASTORE, // -
0325:                // -3, //FASTORE, // -
0326:                // -4, //DASTORE, // -
0327:                // -3, //AASTORE, // -
0328:                // -3, //BASTORE, // -
0329:                // -3, //CASTORE, // -
0330:                // -3, //SASTORE, // -
0331:                // -1, //POP, // -
0332:                // -2, //POP2, // -
0333:                // 1, //DUP, // -
0334:                // 1, //DUP_X1, // -
0335:                // 1, //DUP_X2, // -
0336:                // 2, //DUP2, // -
0337:                // 2, //DUP2_X1, // -
0338:                // 2, //DUP2_X2, // -
0339:                // 0, //SWAP, // -
0340:                // -1, //IADD, // -
0341:                // -2, //LADD, // -
0342:                // -1, //FADD, // -
0343:                // -2, //DADD, // -
0344:                // -1, //ISUB, // -
0345:                // -2, //LSUB, // -
0346:                // -1, //FSUB, // -
0347:                // -2, //DSUB, // -
0348:                // -1, //IMUL, // -
0349:                // -2, //LMUL, // -
0350:                // -1, //FMUL, // -
0351:                // -2, //DMUL, // -
0352:                // -1, //IDIV, // -
0353:                // -2, //LDIV, // -
0354:                // -1, //FDIV, // -
0355:                // -2, //DDIV, // -
0356:                // -1, //IREM, // -
0357:                // -2, //LREM, // -
0358:                // -1, //FREM, // -
0359:                // -2, //DREM, // -
0360:                // 0, //INEG, // -
0361:                // 0, //LNEG, // -
0362:                // 0, //FNEG, // -
0363:                // 0, //DNEG, // -
0364:                // -1, //ISHL, // -
0365:                // -1, //LSHL, // -
0366:                // -1, //ISHR, // -
0367:                // -1, //LSHR, // -
0368:                // -1, //IUSHR, // -
0369:                // -1, //LUSHR, // -
0370:                // -1, //IAND, // -
0371:                // -2, //LAND, // -
0372:                // -1, //IOR, // -
0373:                // -2, //LOR, // -
0374:                // -1, //IXOR, // -
0375:                // -2, //LXOR, // -
0376:                // 0, //IINC, // visitIincInsn
0377:                // 1, //I2L, // visitInsn
0378:                // 0, //I2F, // -
0379:                // 1, //I2D, // -
0380:                // -1, //L2I, // -
0381:                // -1, //L2F, // -
0382:                // 0, //L2D, // -
0383:                // 0, //F2I, // -
0384:                // 1, //F2L, // -
0385:                // 1, //F2D, // -
0386:                // -1, //D2I, // -
0387:                // 0, //D2L, // -
0388:                // -1, //D2F, // -
0389:                // 0, //I2B, // -
0390:                // 0, //I2C, // -
0391:                // 0, //I2S, // -
0392:                // -3, //LCMP, // -
0393:                // -1, //FCMPL, // -
0394:                // -1, //FCMPG, // -
0395:                // -3, //DCMPL, // -
0396:                // -3, //DCMPG, // -
0397:                // -1, //IFEQ, // visitJumpInsn
0398:                // -1, //IFNE, // -
0399:                // -1, //IFLT, // -
0400:                // -1, //IFGE, // -
0401:                // -1, //IFGT, // -
0402:                // -1, //IFLE, // -
0403:                // -2, //IF_ICMPEQ, // -
0404:                // -2, //IF_ICMPNE, // -
0405:                // -2, //IF_ICMPLT, // -
0406:                // -2, //IF_ICMPGE, // -
0407:                // -2, //IF_ICMPGT, // -
0408:                // -2, //IF_ICMPLE, // -
0409:                // -2, //IF_ACMPEQ, // -
0410:                // -2, //IF_ACMPNE, // -
0411:                // 0, //GOTO, // -
0412:                // 1, //JSR, // -
0413:                // 0, //RET, // visitVarInsn
0414:                // -1, //TABLESWITCH, // visiTableSwitchInsn
0415:                // -1, //LOOKUPSWITCH, // visitLookupSwitch
0416:                // -1, //IRETURN, // visitInsn
0417:                // -2, //LRETURN, // -
0418:                // -1, //FRETURN, // -
0419:                // -2, //DRETURN, // -
0420:                // -1, //ARETURN, // -
0421:                // 0, //RETURN, // -
0422:                // NA, //GETSTATIC, // visitFieldInsn
0423:                // NA, //PUTSTATIC, // -
0424:                // NA, //GETFIELD, // -
0425:                // NA, //PUTFIELD, // -
0426:                // NA, //INVOKEVIRTUAL, // visitMethodInsn
0427:                // NA, //INVOKESPECIAL, // -
0428:                // NA, //INVOKESTATIC, // -
0429:                // NA, //INVOKEINTERFACE, // -
0430:                // NA, //UNUSED, // NOT VISITED
0431:                // 1, //NEW, // visitTypeInsn
0432:                // 0, //NEWARRAY, // visitIntInsn
0433:                // 0, //ANEWARRAY, // visitTypeInsn
0434:                // 0, //ARRAYLENGTH, // visitInsn
0435:                // NA, //ATHROW, // -
0436:                // 0, //CHECKCAST, // visitTypeInsn
0437:                // 0, //INSTANCEOF, // -
0438:                // -1, //MONITORENTER, // visitInsn
0439:                // -1, //MONITOREXIT, // -
0440:                // NA, //WIDE, // NOT VISITED
0441:                // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
0442:                // -1, //IFNULL, // visitJumpInsn
0443:                // -1, //IFNONNULL, // -
0444:                // NA, //GOTO_W, // -
0445:                // NA, //JSR_W, // -
0446:                // };
0447:                // for (i = 0; i < b.length; ++i) {
0448:                // System.err.print((char)('E' + b[i]));
0449:                // }
0450:                // System.err.println();
0451:            }
0452:
0453:            /**
0454:             * The label (i.e. basic block) to which these input and output stack map
0455:             * frames correspond.
0456:             */
0457:            Label owner;
0458:
0459:            /**
0460:             * The input stack map frame locals.
0461:             */
0462:            int[] inputLocals;
0463:
0464:            /**
0465:             * The input stack map frame stack.
0466:             */
0467:            int[] inputStack;
0468:
0469:            /**
0470:             * The output stack map frame locals.
0471:             */
0472:            private int[] outputLocals;
0473:
0474:            /**
0475:             * The output stack map frame stack.
0476:             */
0477:            private int[] outputStack;
0478:
0479:            /**
0480:             * Relative size of the output stack. The exact semantics of this field
0481:             * depends on the algorithm that is used.
0482:             * 
0483:             * When only the maximum stack size is computed, this field is the size of
0484:             * the output stack relatively to the top of the input stack.
0485:             * 
0486:             * When the stack map frames are completely computed, this field is the
0487:             * actual number of types in {@link #outputStack}.
0488:             */
0489:            private int outputStackTop;
0490:
0491:            /**
0492:             * Number of types that are initialized in the basic block.
0493:             * 
0494:             * @see #initializations
0495:             */
0496:            private int initializationCount;
0497:
0498:            /**
0499:             * The types that are initialized in the basic block. A constructor
0500:             * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
0501:             * <i>every occurence</i> of this type in the local variables and in the
0502:             * operand stack. This cannot be done during the first phase of the
0503:             * algorithm since, during this phase, the local variables and the operand
0504:             * stack are not completely computed. It is therefore necessary to store the
0505:             * types on which constructors are invoked in the basic block, in order to
0506:             * do this replacement during the second phase of the algorithm, where the
0507:             * frames are fully computed. Note that this array can contain types that
0508:             * are relative to input locals or to the input stack (see below for the
0509:             * description of the algorithm).
0510:             */
0511:            private int[] initializations;
0512:
0513:            /**
0514:             * Returns the output frame local variable type at the given index.
0515:             * 
0516:             * @param local the index of the local that must be returned.
0517:             * @return the output frame local variable type at the given index.
0518:             */
0519:            private int get(final int local) {
0520:                if (outputLocals == null || local >= outputLocals.length) {
0521:                    // this local has never been assigned in this basic block,
0522:                    // so it is still equal to its value in the input frame
0523:                    return LOCAL | local;
0524:                } else {
0525:                    int type = outputLocals[local];
0526:                    if (type == 0) {
0527:                        // this local has never been assigned in this basic block,
0528:                        // so it is still equal to its value in the input frame
0529:                        type = outputLocals[local] = LOCAL | local;
0530:                    }
0531:                    return type;
0532:                }
0533:            }
0534:
0535:            /**
0536:             * Sets the output frame local variable type at the given index.
0537:             * 
0538:             * @param local the index of the local that must be set.
0539:             * @param type the value of the local that must be set.
0540:             */
0541:            private void set(final int local, final int type) {
0542:                // creates and/or resizes the output local variables array if necessary
0543:                if (outputLocals == null) {
0544:                    outputLocals = new int[10];
0545:                }
0546:                int n = outputLocals.length;
0547:                if (local >= n) {
0548:                    int[] t = new int[Math.max(local + 1, 2 * n)];
0549:                    System.arraycopy(outputLocals, 0, t, 0, n);
0550:                    outputLocals = t;
0551:                }
0552:                // sets the local variable
0553:                outputLocals[local] = type;
0554:            }
0555:
0556:            /**
0557:             * Pushes a new type onto the output frame stack.
0558:             * 
0559:             * @param type the type that must be pushed.
0560:             */
0561:            private void push(final int type) {
0562:                // creates and/or resizes the output stack array if necessary
0563:                if (outputStack == null) {
0564:                    outputStack = new int[10];
0565:                }
0566:                int n = outputStack.length;
0567:                if (outputStackTop >= n) {
0568:                    int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
0569:                    System.arraycopy(outputStack, 0, t, 0, n);
0570:                    outputStack = t;
0571:                }
0572:                // pushes the type on the output stack
0573:                outputStack[outputStackTop++] = type;
0574:                // updates the maximun height reached by the output stack, if needed
0575:                int top = owner.inputStackTop + outputStackTop;
0576:                if (top > owner.outputStackMax) {
0577:                    owner.outputStackMax = top;
0578:                }
0579:            }
0580:
0581:            /**
0582:             * Pushes a new type onto the output frame stack.
0583:             * 
0584:             * @param cw the ClassWriter to which this label belongs.
0585:             * @param desc the descriptor of the type to be pushed. Can also be a method
0586:             *        descriptor (in this case this method pushes its return type onto
0587:             *        the output frame stack).
0588:             */
0589:            private void push(final ClassWriter cw, final String desc) {
0590:                int type = type(cw, desc);
0591:                if (type != 0) {
0592:                    push(type);
0593:                    if (type == LONG || type == DOUBLE) {
0594:                        push(TOP);
0595:                    }
0596:                }
0597:            }
0598:
0599:            /**
0600:             * Returns the int encoding of the given type.
0601:             * 
0602:             * @param cw the ClassWriter to which this label belongs.
0603:             * @param desc a type descriptor.
0604:             * @return the int encoding of the given type.
0605:             */
0606:            private int type(final ClassWriter cw, final String desc) {
0607:                String t;
0608:                int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
0609:                switch (desc.charAt(index)) {
0610:                case 'V':
0611:                    return 0;
0612:                case 'Z':
0613:                case 'C':
0614:                case 'B':
0615:                case 'S':
0616:                case 'I':
0617:                    return INTEGER;
0618:                case 'F':
0619:                    return FLOAT;
0620:                case 'J':
0621:                    return LONG;
0622:                case 'D':
0623:                    return DOUBLE;
0624:                case 'L':
0625:                    // stores the internal name, not the descriptor!
0626:                    t = desc.substring(index + 1, desc.length() - 1);
0627:                    return OBJECT | cw.addType(t);
0628:                    // case '[':
0629:                default:
0630:                    // extracts the dimensions and the element type
0631:                    int data;
0632:                    int dims = index + 1;
0633:                    while (desc.charAt(dims) == '[') {
0634:                        ++dims;
0635:                    }
0636:                    switch (desc.charAt(dims)) {
0637:                    case 'Z':
0638:                        data = BOOLEAN;
0639:                        break;
0640:                    case 'C':
0641:                        data = CHAR;
0642:                        break;
0643:                    case 'B':
0644:                        data = BYTE;
0645:                        break;
0646:                    case 'S':
0647:                        data = SHORT;
0648:                        break;
0649:                    case 'I':
0650:                        data = INTEGER;
0651:                        break;
0652:                    case 'F':
0653:                        data = FLOAT;
0654:                        break;
0655:                    case 'J':
0656:                        data = LONG;
0657:                        break;
0658:                    case 'D':
0659:                        data = DOUBLE;
0660:                        break;
0661:                    // case 'L':
0662:                    default:
0663:                        // stores the internal name, not the descriptor
0664:                        t = desc.substring(dims + 1, desc.length() - 1);
0665:                        data = OBJECT | cw.addType(t);
0666:                    }
0667:                    return (dims - index) << 28 | data;
0668:                }
0669:            }
0670:
0671:            /**
0672:             * Pops a type from the output frame stack and returns its value.
0673:             * 
0674:             * @return the type that has been popped from the output frame stack.
0675:             */
0676:            private int pop() {
0677:                if (outputStackTop > 0) {
0678:                    return outputStack[--outputStackTop];
0679:                } else {
0680:                    // if the output frame stack is empty, pops from the input stack
0681:                    return STACK | -(--owner.inputStackTop);
0682:                }
0683:            }
0684:
0685:            /**
0686:             * Pops the given number of types from the output frame stack.
0687:             * 
0688:             * @param elements the number of types that must be popped.
0689:             */
0690:            private void pop(final int elements) {
0691:                if (outputStackTop >= elements) {
0692:                    outputStackTop -= elements;
0693:                } else {
0694:                    // if the number of elements to be popped is greater than the number
0695:                    // of elements in the output stack, clear it, and pops the remaining
0696:                    // elements from the input stack.
0697:                    owner.inputStackTop -= elements - outputStackTop;
0698:                    outputStackTop = 0;
0699:                }
0700:            }
0701:
0702:            /**
0703:             * Pops a type from the output frame stack.
0704:             * 
0705:             * @param desc the descriptor of the type to be popped. Can also be a method
0706:             *        descriptor (in this case this method pops the types corresponding
0707:             *        to the method arguments).
0708:             */
0709:            private void pop(final String desc) {
0710:                char c = desc.charAt(0);
0711:                if (c == '(') {
0712:                    pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
0713:                } else if (c == 'J' || c == 'D') {
0714:                    pop(2);
0715:                } else {
0716:                    pop(1);
0717:                }
0718:            }
0719:
0720:            /**
0721:             * Adds a new type to the list of types on which a constructor is invoked in
0722:             * the basic block.
0723:             * 
0724:             * @param var a type on a which a constructor is invoked.
0725:             */
0726:            private void init(final int var) {
0727:                // creates and/or resizes the initializations array if necessary
0728:                if (initializations == null) {
0729:                    initializations = new int[2];
0730:                }
0731:                int n = initializations.length;
0732:                if (initializationCount >= n) {
0733:                    int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
0734:                    System.arraycopy(initializations, 0, t, 0, n);
0735:                    initializations = t;
0736:                }
0737:                // stores the type to be initialized
0738:                initializations[initializationCount++] = var;
0739:            }
0740:
0741:            /**
0742:             * Replaces the given type with the appropriate type if it is one of the
0743:             * types on which a constructor is invoked in the basic block.
0744:             * 
0745:             * @param cw the ClassWriter to which this label belongs.
0746:             * @param t a type
0747:             * @return t or, if t is one of the types on which a constructor is invoked
0748:             *         in the basic block, the type corresponding to this constructor.
0749:             */
0750:            private int init(final ClassWriter cw, final int t) {
0751:                int s;
0752:                if (t == UNINITIALIZED_THIS) {
0753:                    s = OBJECT | cw.addType(cw.this Name);
0754:                } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
0755:                    String type = cw.typeTable[t & BASE_VALUE].strVal1;
0756:                    s = OBJECT | cw.addType(type);
0757:                } else {
0758:                    return t;
0759:                }
0760:                for (int j = 0; j < initializationCount; ++j) {
0761:                    int u = initializations[j];
0762:                    int dim = u & DIM;
0763:                    int kind = u & KIND;
0764:                    if (kind == LOCAL) {
0765:                        u = dim + inputLocals[u & VALUE];
0766:                    } else if (kind == STACK) {
0767:                        u = dim + inputStack[inputStack.length - (u & VALUE)];
0768:                    }
0769:                    if (t == u) {
0770:                        return s;
0771:                    }
0772:                }
0773:                return t;
0774:            }
0775:
0776:            /**
0777:             * Initializes the input frame of the first basic block from the method
0778:             * descriptor.
0779:             * 
0780:             * @param cw the ClassWriter to which this label belongs.
0781:             * @param access the access flags of the method to which this label belongs.
0782:             * @param args the formal parameter types of this method.
0783:             * @param maxLocals the maximum number of local variables of this method.
0784:             */
0785:            void initInputFrame(final ClassWriter cw, final int access,
0786:                    final Type[] args, final int maxLocals) {
0787:                inputLocals = new int[maxLocals];
0788:                inputStack = new int[0];
0789:                int i = 0;
0790:                if ((access & Opcodes.ACC_STATIC) == 0) {
0791:                    if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
0792:                        inputLocals[i++] = OBJECT | cw.addType(cw.this Name);
0793:                    } else {
0794:                        inputLocals[i++] = UNINITIALIZED_THIS;
0795:                    }
0796:                }
0797:                for (int j = 0; j < args.length; ++j) {
0798:                    int t = type(cw, args[j].getDescriptor());
0799:                    inputLocals[i++] = t;
0800:                    if (t == LONG || t == DOUBLE) {
0801:                        inputLocals[i++] = TOP;
0802:                    }
0803:                }
0804:                while (i < maxLocals) {
0805:                    inputLocals[i++] = TOP;
0806:                }
0807:            }
0808:
0809:            /**
0810:             * Simulates the action of the given instruction on the output stack frame.
0811:             * 
0812:             * @param opcode the opcode of the instruction.
0813:             * @param arg the operand of the instruction, if any.
0814:             * @param cw the class writer to which this label belongs.
0815:             * @param item the operand of the instructions, if any.
0816:             */
0817:            void execute(final int opcode, final int arg, final ClassWriter cw,
0818:                    final Item item) {
0819:                int t1, t2, t3, t4;
0820:                switch (opcode) {
0821:                case Opcodes.NOP:
0822:                case Opcodes.INEG:
0823:                case Opcodes.LNEG:
0824:                case Opcodes.FNEG:
0825:                case Opcodes.DNEG:
0826:                case Opcodes.I2B:
0827:                case Opcodes.I2C:
0828:                case Opcodes.I2S:
0829:                case Opcodes.GOTO:
0830:                case Opcodes.RETURN:
0831:                    break;
0832:                case Opcodes.ACONST_NULL:
0833:                    push(NULL);
0834:                    break;
0835:                case Opcodes.ICONST_M1:
0836:                case Opcodes.ICONST_0:
0837:                case Opcodes.ICONST_1:
0838:                case Opcodes.ICONST_2:
0839:                case Opcodes.ICONST_3:
0840:                case Opcodes.ICONST_4:
0841:                case Opcodes.ICONST_5:
0842:                case Opcodes.BIPUSH:
0843:                case Opcodes.SIPUSH:
0844:                case Opcodes.ILOAD:
0845:                    push(INTEGER);
0846:                    break;
0847:                case Opcodes.LCONST_0:
0848:                case Opcodes.LCONST_1:
0849:                case Opcodes.LLOAD:
0850:                    push(LONG);
0851:                    push(TOP);
0852:                    break;
0853:                case Opcodes.FCONST_0:
0854:                case Opcodes.FCONST_1:
0855:                case Opcodes.FCONST_2:
0856:                case Opcodes.FLOAD:
0857:                    push(FLOAT);
0858:                    break;
0859:                case Opcodes.DCONST_0:
0860:                case Opcodes.DCONST_1:
0861:                case Opcodes.DLOAD:
0862:                    push(DOUBLE);
0863:                    push(TOP);
0864:                    break;
0865:                case Opcodes.LDC:
0866:                    switch (item.type) {
0867:                    case ClassWriter.INT:
0868:                        push(INTEGER);
0869:                        break;
0870:                    case ClassWriter.LONG:
0871:                        push(LONG);
0872:                        push(TOP);
0873:                        break;
0874:                    case ClassWriter.FLOAT:
0875:                        push(FLOAT);
0876:                        break;
0877:                    case ClassWriter.DOUBLE:
0878:                        push(DOUBLE);
0879:                        push(TOP);
0880:                        break;
0881:                    case ClassWriter.CLASS:
0882:                        push(OBJECT | cw.addType("java/lang/Class"));
0883:                        break;
0884:                    // case ClassWriter.STR:
0885:                    default:
0886:                        push(OBJECT | cw.addType("java/lang/String"));
0887:                    }
0888:                    break;
0889:                case Opcodes.ALOAD:
0890:                    push(get(arg));
0891:                    break;
0892:                case Opcodes.IALOAD:
0893:                case Opcodes.BALOAD:
0894:                case Opcodes.CALOAD:
0895:                case Opcodes.SALOAD:
0896:                    pop(2);
0897:                    push(INTEGER);
0898:                    break;
0899:                case Opcodes.LALOAD:
0900:                case Opcodes.D2L:
0901:                    pop(2);
0902:                    push(LONG);
0903:                    push(TOP);
0904:                    break;
0905:                case Opcodes.FALOAD:
0906:                    pop(2);
0907:                    push(FLOAT);
0908:                    break;
0909:                case Opcodes.DALOAD:
0910:                case Opcodes.L2D:
0911:                    pop(2);
0912:                    push(DOUBLE);
0913:                    push(TOP);
0914:                    break;
0915:                case Opcodes.AALOAD:
0916:                    pop(1);
0917:                    t1 = pop();
0918:                    push(ELEMENT_OF + t1);
0919:                    break;
0920:                case Opcodes.ISTORE:
0921:                case Opcodes.FSTORE:
0922:                case Opcodes.ASTORE:
0923:                    t1 = pop();
0924:                    set(arg, t1);
0925:                    if (arg > 0) {
0926:                        t2 = get(arg - 1);
0927:                        // if t2 is of kind STACK or LOCAL we cannot know its size!
0928:                        if (t2 == LONG || t2 == DOUBLE) {
0929:                            set(arg - 1, TOP);
0930:                        }
0931:                    }
0932:                    break;
0933:                case Opcodes.LSTORE:
0934:                case Opcodes.DSTORE:
0935:                    pop(1);
0936:                    t1 = pop();
0937:                    set(arg, t1);
0938:                    set(arg + 1, TOP);
0939:                    if (arg > 0) {
0940:                        t2 = get(arg - 1);
0941:                        // if t2 is of kind STACK or LOCAL we cannot know its size!
0942:                        if (t2 == LONG || t2 == DOUBLE) {
0943:                            set(arg - 1, TOP);
0944:                        }
0945:                    }
0946:                    break;
0947:                case Opcodes.IASTORE:
0948:                case Opcodes.BASTORE:
0949:                case Opcodes.CASTORE:
0950:                case Opcodes.SASTORE:
0951:                case Opcodes.FASTORE:
0952:                case Opcodes.AASTORE:
0953:                    pop(3);
0954:                    break;
0955:                case Opcodes.LASTORE:
0956:                case Opcodes.DASTORE:
0957:                    pop(4);
0958:                    break;
0959:                case Opcodes.POP:
0960:                case Opcodes.IFEQ:
0961:                case Opcodes.IFNE:
0962:                case Opcodes.IFLT:
0963:                case Opcodes.IFGE:
0964:                case Opcodes.IFGT:
0965:                case Opcodes.IFLE:
0966:                case Opcodes.IRETURN:
0967:                case Opcodes.FRETURN:
0968:                case Opcodes.ARETURN:
0969:                case Opcodes.TABLESWITCH:
0970:                case Opcodes.LOOKUPSWITCH:
0971:                case Opcodes.ATHROW:
0972:                case Opcodes.MONITORENTER:
0973:                case Opcodes.MONITOREXIT:
0974:                case Opcodes.IFNULL:
0975:                case Opcodes.IFNONNULL:
0976:                    pop(1);
0977:                    break;
0978:                case Opcodes.POP2:
0979:                case Opcodes.IF_ICMPEQ:
0980:                case Opcodes.IF_ICMPNE:
0981:                case Opcodes.IF_ICMPLT:
0982:                case Opcodes.IF_ICMPGE:
0983:                case Opcodes.IF_ICMPGT:
0984:                case Opcodes.IF_ICMPLE:
0985:                case Opcodes.IF_ACMPEQ:
0986:                case Opcodes.IF_ACMPNE:
0987:                case Opcodes.LRETURN:
0988:                case Opcodes.DRETURN:
0989:                    pop(2);
0990:                    break;
0991:                case Opcodes.DUP:
0992:                    t1 = pop();
0993:                    push(t1);
0994:                    push(t1);
0995:                    break;
0996:                case Opcodes.DUP_X1:
0997:                    t1 = pop();
0998:                    t2 = pop();
0999:                    push(t1);
1000:                    push(t2);
1001:                    push(t1);
1002:                    break;
1003:                case Opcodes.DUP_X2:
1004:                    t1 = pop();
1005:                    t2 = pop();
1006:                    t3 = pop();
1007:                    push(t1);
1008:                    push(t3);
1009:                    push(t2);
1010:                    push(t1);
1011:                    break;
1012:                case Opcodes.DUP2:
1013:                    t1 = pop();
1014:                    t2 = pop();
1015:                    push(t2);
1016:                    push(t1);
1017:                    push(t2);
1018:                    push(t1);
1019:                    break;
1020:                case Opcodes.DUP2_X1:
1021:                    t1 = pop();
1022:                    t2 = pop();
1023:                    t3 = pop();
1024:                    push(t2);
1025:                    push(t1);
1026:                    push(t3);
1027:                    push(t2);
1028:                    push(t1);
1029:                    break;
1030:                case Opcodes.DUP2_X2:
1031:                    t1 = pop();
1032:                    t2 = pop();
1033:                    t3 = pop();
1034:                    t4 = pop();
1035:                    push(t2);
1036:                    push(t1);
1037:                    push(t4);
1038:                    push(t3);
1039:                    push(t2);
1040:                    push(t1);
1041:                    break;
1042:                case Opcodes.SWAP:
1043:                    t1 = pop();
1044:                    t2 = pop();
1045:                    push(t1);
1046:                    push(t2);
1047:                    break;
1048:                case Opcodes.IADD:
1049:                case Opcodes.ISUB:
1050:                case Opcodes.IMUL:
1051:                case Opcodes.IDIV:
1052:                case Opcodes.IREM:
1053:                case Opcodes.IAND:
1054:                case Opcodes.IOR:
1055:                case Opcodes.IXOR:
1056:                case Opcodes.ISHL:
1057:                case Opcodes.ISHR:
1058:                case Opcodes.IUSHR:
1059:                case Opcodes.L2I:
1060:                case Opcodes.D2I:
1061:                case Opcodes.FCMPL:
1062:                case Opcodes.FCMPG:
1063:                    pop(2);
1064:                    push(INTEGER);
1065:                    break;
1066:                case Opcodes.LADD:
1067:                case Opcodes.LSUB:
1068:                case Opcodes.LMUL:
1069:                case Opcodes.LDIV:
1070:                case Opcodes.LREM:
1071:                case Opcodes.LAND:
1072:                case Opcodes.LOR:
1073:                case Opcodes.LXOR:
1074:                    pop(4);
1075:                    push(LONG);
1076:                    push(TOP);
1077:                    break;
1078:                case Opcodes.FADD:
1079:                case Opcodes.FSUB:
1080:                case Opcodes.FMUL:
1081:                case Opcodes.FDIV:
1082:                case Opcodes.FREM:
1083:                case Opcodes.L2F:
1084:                case Opcodes.D2F:
1085:                    pop(2);
1086:                    push(FLOAT);
1087:                    break;
1088:                case Opcodes.DADD:
1089:                case Opcodes.DSUB:
1090:                case Opcodes.DMUL:
1091:                case Opcodes.DDIV:
1092:                case Opcodes.DREM:
1093:                    pop(4);
1094:                    push(DOUBLE);
1095:                    push(TOP);
1096:                    break;
1097:                case Opcodes.LSHL:
1098:                case Opcodes.LSHR:
1099:                case Opcodes.LUSHR:
1100:                    pop(3);
1101:                    push(LONG);
1102:                    push(TOP);
1103:                    break;
1104:                case Opcodes.IINC:
1105:                    set(arg, INTEGER);
1106:                    break;
1107:                case Opcodes.I2L:
1108:                case Opcodes.F2L:
1109:                    pop(1);
1110:                    push(LONG);
1111:                    push(TOP);
1112:                    break;
1113:                case Opcodes.I2F:
1114:                    pop(1);
1115:                    push(FLOAT);
1116:                    break;
1117:                case Opcodes.I2D:
1118:                case Opcodes.F2D:
1119:                    pop(1);
1120:                    push(DOUBLE);
1121:                    push(TOP);
1122:                    break;
1123:                case Opcodes.F2I:
1124:                case Opcodes.ARRAYLENGTH:
1125:                case Opcodes.INSTANCEOF:
1126:                    pop(1);
1127:                    push(INTEGER);
1128:                    break;
1129:                case Opcodes.LCMP:
1130:                case Opcodes.DCMPL:
1131:                case Opcodes.DCMPG:
1132:                    pop(4);
1133:                    push(INTEGER);
1134:                    break;
1135:                case Opcodes.JSR:
1136:                case Opcodes.RET:
1137:                    throw new RuntimeException(
1138:                            "JSR/RET are not supported with computeFrames option");
1139:                case Opcodes.GETSTATIC:
1140:                    push(cw, item.strVal3);
1141:                    break;
1142:                case Opcodes.PUTSTATIC:
1143:                    pop(item.strVal3);
1144:                    break;
1145:                case Opcodes.GETFIELD:
1146:                    pop(1);
1147:                    push(cw, item.strVal3);
1148:                    break;
1149:                case Opcodes.PUTFIELD:
1150:                    pop(item.strVal3);
1151:                    pop();
1152:                    break;
1153:                case Opcodes.INVOKEVIRTUAL:
1154:                case Opcodes.INVOKESPECIAL:
1155:                case Opcodes.INVOKESTATIC:
1156:                case Opcodes.INVOKEINTERFACE:
1157:                    pop(item.strVal3);
1158:                    if (opcode != Opcodes.INVOKESTATIC) {
1159:                        t1 = pop();
1160:                        if (opcode == Opcodes.INVOKESPECIAL
1161:                                && item.strVal2.charAt(0) == '<') {
1162:                            init(t1);
1163:                        }
1164:                    }
1165:                    push(cw, item.strVal3);
1166:                    break;
1167:                case Opcodes.NEW:
1168:                    push(UNINITIALIZED
1169:                            | cw.addUninitializedType(item.strVal1, arg));
1170:                    break;
1171:                case Opcodes.NEWARRAY:
1172:                    pop();
1173:                    switch (arg) {
1174:                    case Opcodes.T_BOOLEAN:
1175:                        push(ARRAY_OF | BOOLEAN);
1176:                        break;
1177:                    case Opcodes.T_CHAR:
1178:                        push(ARRAY_OF | CHAR);
1179:                        break;
1180:                    case Opcodes.T_BYTE:
1181:                        push(ARRAY_OF | BYTE);
1182:                        break;
1183:                    case Opcodes.T_SHORT:
1184:                        push(ARRAY_OF | SHORT);
1185:                        break;
1186:                    case Opcodes.T_INT:
1187:                        push(ARRAY_OF | INTEGER);
1188:                        break;
1189:                    case Opcodes.T_FLOAT:
1190:                        push(ARRAY_OF | FLOAT);
1191:                        break;
1192:                    case Opcodes.T_DOUBLE:
1193:                        push(ARRAY_OF | DOUBLE);
1194:                        break;
1195:                    // case Opcodes.T_LONG:
1196:                    default:
1197:                        push(ARRAY_OF | LONG);
1198:                        break;
1199:                    }
1200:                    break;
1201:                case Opcodes.ANEWARRAY:
1202:                    String s = item.strVal1;
1203:                    pop();
1204:                    if (s.charAt(0) == '[') {
1205:                        push(cw, "[" + s);
1206:                    } else {
1207:                        push(ARRAY_OF | OBJECT | cw.addType(s));
1208:                    }
1209:                    break;
1210:                case Opcodes.CHECKCAST:
1211:                    s = item.strVal1;
1212:                    pop();
1213:                    if (s.charAt(0) == '[') {
1214:                        push(cw, s);
1215:                    } else {
1216:                        push(OBJECT | cw.addType(s));
1217:                    }
1218:                    break;
1219:                // case Opcodes.MULTIANEWARRAY:
1220:                default:
1221:                    pop(arg);
1222:                    push(cw, item.strVal1);
1223:                    break;
1224:                }
1225:            }
1226:
1227:            /**
1228:             * Merges the input frame of the given basic block with the input and output
1229:             * frames of this basic block. Returns <tt>true</tt> if the input frame of
1230:             * the given label has been changed by this operation.
1231:             * 
1232:             * @param cw the ClassWriter to which this label belongs.
1233:             * @param frame the basic block whose input frame must be updated.
1234:             * @param edge the kind of the {@link Edge} between this label and 'label'.
1235:             *        See {@link Edge#info}.
1236:             * @return <tt>true</tt> if the input frame of the given label has been
1237:             *         changed by this operation.
1238:             */
1239:            boolean merge(final ClassWriter cw, final Frame frame,
1240:                    final int edge) {
1241:                boolean changed = false;
1242:                int i, s, dim, kind, t;
1243:
1244:                int nLocal = inputLocals.length;
1245:                int nStack = inputStack.length;
1246:                if (frame.inputLocals == null) {
1247:                    frame.inputLocals = new int[nLocal];
1248:                    changed = true;
1249:                }
1250:
1251:                for (i = 0; i < nLocal; ++i) {
1252:                    if (outputLocals != null && i < outputLocals.length) {
1253:                        s = outputLocals[i];
1254:                        if (s == 0) {
1255:                            t = inputLocals[i];
1256:                        } else {
1257:                            dim = s & DIM;
1258:                            kind = s & KIND;
1259:                            if (kind == LOCAL) {
1260:                                t = dim + inputLocals[s & VALUE];
1261:                            } else if (kind == STACK) {
1262:                                t = dim + inputStack[nStack - (s & VALUE)];
1263:                            } else {
1264:                                t = s;
1265:                            }
1266:                        }
1267:                    } else {
1268:                        t = inputLocals[i];
1269:                    }
1270:                    if (initializations != null) {
1271:                        t = init(cw, t);
1272:                    }
1273:                    changed |= merge(cw, t, frame.inputLocals, i);
1274:                }
1275:
1276:                if (edge > 0) {
1277:                    for (i = 0; i < nLocal; ++i) {
1278:                        t = inputLocals[i];
1279:                        changed |= merge(cw, t, frame.inputLocals, i);
1280:                    }
1281:                    if (frame.inputStack == null) {
1282:                        frame.inputStack = new int[1];
1283:                        changed = true;
1284:                    }
1285:                    changed |= merge(cw, edge, frame.inputStack, 0);
1286:                    return changed;
1287:                }
1288:
1289:                int nInputStack = inputStack.length + owner.inputStackTop;
1290:                if (frame.inputStack == null) {
1291:                    frame.inputStack = new int[nInputStack + outputStackTop];
1292:                    changed = true;
1293:                }
1294:
1295:                for (i = 0; i < nInputStack; ++i) {
1296:                    t = inputStack[i];
1297:                    if (initializations != null) {
1298:                        t = init(cw, t);
1299:                    }
1300:                    changed |= merge(cw, t, frame.inputStack, i);
1301:                }
1302:                for (i = 0; i < outputStackTop; ++i) {
1303:                    s = outputStack[i];
1304:                    dim = s & DIM;
1305:                    kind = s & KIND;
1306:                    if (kind == LOCAL) {
1307:                        t = dim + inputLocals[s & VALUE];
1308:                    } else if (kind == STACK) {
1309:                        t = dim + inputStack[nStack - (s & VALUE)];
1310:                    } else {
1311:                        t = s;
1312:                    }
1313:                    if (initializations != null) {
1314:                        t = init(cw, t);
1315:                    }
1316:                    changed |= merge(cw, t, frame.inputStack, nInputStack + i);
1317:                }
1318:                return changed;
1319:            }
1320:
1321:            /**
1322:             * Merges the type at the given index in the given type array with the given
1323:             * type. Returns <tt>true</tt> if the type array has been modified by this
1324:             * operation.
1325:             * 
1326:             * @param cw the ClassWriter to which this label belongs.
1327:             * @param t the type with which the type array element must be merged.
1328:             * @param types an array of types.
1329:             * @param index the index of the type that must be merged in 'types'.
1330:             * @return <tt>true</tt> if the type array has been modified by this
1331:             *         operation.
1332:             */
1333:            private boolean merge(final ClassWriter cw, int t,
1334:                    final int[] types, final int index) {
1335:                int u = types[index];
1336:                if (u == t) {
1337:                    // if the types are equal, merge(u,t)=u, so there is no change
1338:                    return false;
1339:                }
1340:                if ((t & ~DIM) == NULL) {
1341:                    if (u == NULL) {
1342:                        return false;
1343:                    }
1344:                    t = NULL;
1345:                }
1346:                if (u == 0) {
1347:                    // if types[index] has never been assigned, merge(u,t)=t
1348:                    types[index] = t;
1349:                    return true;
1350:                }
1351:                int v;
1352:                if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
1353:                    // if u is a reference type of any dimension
1354:                    if (t == NULL) {
1355:                        // if t is the NULL type, merge(u,t)=u, so there is no change
1356:                        return false;
1357:                    } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
1358:                        if ((u & BASE_KIND) == OBJECT) {
1359:                            // if t is also a reference type, and if u and t have the
1360:                            // same dimension merge(u,t) = dim(t) | common parent of the
1361:                            // element types of u and t
1362:                            v = (t & DIM)
1363:                                    | OBJECT
1364:                                    | cw.getMergedType(t & BASE_VALUE, u
1365:                                            & BASE_VALUE);
1366:                        } else {
1367:                            // if u and t are array types, but not with the same element
1368:                            // type, merge(u,t)=java/lang/Object
1369:                            v = OBJECT | cw.addType("java/lang/Object");
1370:                        }
1371:                    } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
1372:                        // if t is any other reference or array type,
1373:                        // merge(u,t)=java/lang/Object
1374:                        v = OBJECT | cw.addType("java/lang/Object");
1375:                    } else {
1376:                        // if t is any other type, merge(u,t)=TOP
1377:                        v = TOP;
1378:                    }
1379:                } else if (u == NULL) {
1380:                    // if u is the NULL type, merge(u,t)=t,
1381:                    // or TOP if t is not a reference type
1382:                    v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
1383:                } else {
1384:                    // if u is any other type, merge(u,t)=TOP whatever t
1385:                    v = TOP;
1386:                }
1387:                if (u != v) {
1388:                    types[index] = v;
1389:                    return true;
1390:                }
1391:                return false;
1392:            }
1393:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.