Source Code Cross Referenced for TypesMethodVisitor.java in  » Web-Framework » rife-1.6.1 » com » uwyn » rife » continuations » instrument » 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 » Web Framework » rife 1.6.1 » com.uwyn.rife.continuations.instrument 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
0003:         * Distributed under the terms of either:
0004:         * - the common development and distribution license (CDDL), v1.0; or
0005:         * - the GNU Lesser General Public License, v2.1 or later
0006:         * $Id: TypesMethodVisitor.java 3805 2007-06-23 20:18:19Z gbevin $
0007:         */
0008:        package com.uwyn.rife.continuations.instrument;
0009:
0010:        import com.uwyn.rife.asm.*;
0011:
0012:        import com.uwyn.rife.continuations.ContinuationConfigInstrument;
0013:        import com.uwyn.rife.continuations.instrument.NoOpAnnotationVisitor;
0014:        import java.util.ArrayList;
0015:        import java.util.HashMap;
0016:        import java.util.LinkedHashMap;
0017:        import java.util.List;
0018:        import java.util.Map;
0019:        import java.util.logging.Level;
0020:
0021:        import static com.uwyn.rife.continuations.instrument.ContinuationDebug.*;
0022:        import static com.uwyn.rife.continuations.instrument.TypesContext.*;
0023:
0024:        class TypesMethodVisitor implements  MethodVisitor, Opcodes {
0025:            private final static int T_BOOLEAN = 4;
0026:            private final static int T_CHAR = 5;
0027:            private final static int T_FLOAT = 6;
0028:            private final static int T_DOUBLE = 7;
0029:            private final static int T_BYTE = 8;
0030:            private final static int T_SHORT = 9;
0031:            private final static int T_INT = 10;
0032:            private final static int T_LONG = 11;
0033:
0034:            private ContinuationConfigInstrument mConfig = null;
0035:
0036:            private TypesClassVisitor mClassVisitor = null;
0037:
0038:            private String mClassName = null;
0039:            private String mClassNameInternal = null;
0040:
0041:            private TypesNode mCurrentNode = null;
0042:            private TypesNode mRootNode = null;
0043:
0044:            private HashMap<Label, TypesNode> mLabelMapping = null;
0045:            private LinkedHashMap<Label, List<Label>> mTryCatchHandlers = null;
0046:            private TypesContext[] mPauseContexts = null;
0047:            private TypesContext[] mLabelContexts = null;
0048:
0049:            private int mPausecount = -1;
0050:            private int mLabelcount = -1;
0051:
0052:            private NoOpAnnotationVisitor mAnnotationVisitor = new NoOpAnnotationVisitor();
0053:
0054:            TypesMethodVisitor(ContinuationConfigInstrument config,
0055:                    TypesClassVisitor classVisitor, String className) {
0056:                mConfig = config;
0057:                mClassVisitor = classVisitor;
0058:                mClassName = className;
0059:                mClassNameInternal = mClassName.replace('.', '/');
0060:
0061:                mLabelMapping = new HashMap<Label, TypesNode>();
0062:                mTryCatchHandlers = new LinkedHashMap<Label, List<Label>>();
0063:
0064:                // pushes the first block onto the stack of blocks to be visited
0065:                mCurrentNode = new TypesNode();
0066:                mRootNode = mCurrentNode;
0067:            }
0068:
0069:            /**
0070:             * Visits a local variable instruction. A local variable instruction is an
0071:             * instruction that loads or stores the value of a local variable.
0072:             *
0073:             * @param opcode the opcode of the local variable instruction to be visited.
0074:             *      This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
0075:             *      LSTORE, FSTORE, DSTORE, ASTORE or RET.
0076:             * @param var the operand of the instruction to be visited. This operand is
0077:             *      the index of a local variable.
0078:             */
0079:            public void visitVarInsn(int opcode, int var) {
0080:                ///CLOVER:OFF
0081:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0082:                    ContinuationDebug.LOGGER
0083:                            .finest(" Type:visitVarInsn            ("
0084:                                    + OPCODES[opcode] + ", " + var + ")");
0085:                ///CLOVER:ON
0086:
0087:                if (mCurrentNode != null) {
0088:                    switch (opcode) {
0089:                    // store primitive variable
0090:                    case ISTORE:
0091:                        mCurrentNode.addInstruction(new TypesInstruction(
0092:                                TypesOpcode.SET, var, CAT1_INT));
0093:                        break;
0094:                    case FSTORE:
0095:                        mCurrentNode.addInstruction(new TypesInstruction(
0096:                                TypesOpcode.SET, var, CAT1_FLOAT));
0097:                        break;
0098:                    case LSTORE:
0099:                        mCurrentNode.addInstruction(new TypesInstruction(
0100:                                TypesOpcode.SET, var, CAT2_LONG));
0101:                        break;
0102:                    case DSTORE:
0103:                        mCurrentNode.addInstruction(new TypesInstruction(
0104:                                TypesOpcode.SET, var, CAT2_DOUBLE));
0105:                        break;
0106:                    // store reference var
0107:                    case ASTORE:
0108:                        mCurrentNode.addInstruction(new TypesInstruction(
0109:                                TypesOpcode.SET, var, null));
0110:                        break;
0111:                    // load primitive var
0112:                    case ILOAD:
0113:                        mCurrentNode.addInstruction(new TypesInstruction(
0114:                                TypesOpcode.GET, var, CAT1_INT));
0115:                        break;
0116:                    case FLOAD:
0117:                        mCurrentNode.addInstruction(new TypesInstruction(
0118:                                TypesOpcode.GET, var, CAT1_FLOAT));
0119:                        break;
0120:                    case LLOAD:
0121:                        mCurrentNode.addInstruction(new TypesInstruction(
0122:                                TypesOpcode.GET, var, CAT2_LONG));
0123:                        break;
0124:                    case DLOAD:
0125:                        mCurrentNode.addInstruction(new TypesInstruction(
0126:                                TypesOpcode.GET, var, CAT2_DOUBLE));
0127:                        break;
0128:                    // load reference var
0129:                    case ALOAD:
0130:                        if (0 == var) {
0131:                            mCurrentNode.addInstruction(new TypesInstruction(
0132:                                    TypesOpcode.GET, var, mClassNameInternal));
0133:                        } else {
0134:                            mCurrentNode.addInstruction(new TypesInstruction(
0135:                                    TypesOpcode.GET, var, null));
0136:                        }
0137:                        break;
0138:                    // no stack change, but end of current block (no successor)
0139:                    case RET:
0140:                        mCurrentNode = null;
0141:                        break;
0142:                    }
0143:                }
0144:            }
0145:
0146:            /**
0147:             * Visits a method instruction. A method instruction is an instruction that
0148:             * invokes a method.
0149:             *
0150:             * @param opcode the opcode of the type instruction to be visited. This opcode
0151:             *      is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
0152:             *      INVOKEINTERFACE.
0153:             * @param owner the internal name of the method's owner class (see {@link
0154:             *      Type#getInternalName getInternalName}).
0155:             * @param name the method's name.
0156:             * @param desc the method's descriptor (see {@link Type Type}).
0157:             */
0158:            public void visitMethodInsn(int opcode, String owner, String name,
0159:                    String desc) {
0160:                ///CLOVER:OFF
0161:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0162:                    ContinuationDebug.LOGGER
0163:                            .finest(" Type:visitMethodInsn         ("
0164:                                    + OPCODES[opcode] + ", \"" + owner
0165:                                    + "\", \"" + name + "\", \"" + desc + "\")");
0166:                ///CLOVER:ON
0167:
0168:                if (mCurrentNode != null) {
0169:                    String owner_classname = owner.replace('/', '.');
0170:
0171:                    if ((owner_classname.equals(mConfig
0172:                            .getContinuableSupportClassName()) || mClassName
0173:                            .equals(owner_classname))
0174:                            && ((mConfig.getPauseMethodName().equals(name) && "()V"
0175:                                    .equals(desc))
0176:                                    || (mConfig.getStepbackMethodName().equals(
0177:                                            name) && "()V".equals(desc)) || (mConfig
0178:                                    .getCallMethodName().equals(name) && Type
0179:                                    .getMethodDescriptor(
0180:                                            mConfig.getCallMethodReturnType(),
0181:                                            mConfig
0182:                                                    .getCallMethodArgumentTypes())
0183:                                    .equals(desc)))) {
0184:                        // pop the element instance reference from the stack
0185:                        mCurrentNode.addInstruction(new TypesInstruction(
0186:                                TypesOpcode.POP));
0187:
0188:                        // remember the node in which the pause invocation is called
0189:                        mCurrentNode.addInstruction(new TypesInstruction(
0190:                                TypesOpcode.PAUSE, ++mPausecount));
0191:
0192:                        return;
0193:                    }
0194:                    // not the pause invocation
0195:                    else {
0196:                        // pop off the argument types of the method
0197:                        Type[] arguments = Type.getArgumentTypes(desc);
0198:                        for (int i = 0; i < arguments.length; i++) {
0199:                            mCurrentNode.addInstruction(new TypesInstruction(
0200:                                    TypesOpcode.POP));
0201:                        }
0202:
0203:                        // pop the object reference from the stack if it'd not a static
0204:                        // method invocation
0205:                        if (INVOKESTATIC != opcode) {
0206:                            mCurrentNode.addInstruction(new TypesInstruction(
0207:                                    TypesOpcode.POP));
0208:                        }
0209:
0210:                        // store the return type of the method
0211:                        if (!("<init>".equals(name) && INVOKESPECIAL == opcode)) {
0212:                            Type type = Type.getReturnType(desc);
0213:                            switch (type.getSort()) {
0214:                            case Type.OBJECT:
0215:                                mCurrentNode
0216:                                        .addInstruction(new TypesInstruction(
0217:                                                TypesOpcode.PUSH, type
0218:                                                        .getInternalName()));
0219:                                break;
0220:                            case Type.ARRAY:
0221:                                mCurrentNode
0222:                                        .addInstruction(new TypesInstruction(
0223:                                                TypesOpcode.PUSH, type
0224:                                                        .getDescriptor()));
0225:                                break;
0226:                            case Type.BOOLEAN:
0227:                                mCurrentNode
0228:                                        .addInstruction(new TypesInstruction(
0229:                                                TypesOpcode.PUSH, CAT1_BOOLEAN));
0230:                                break;
0231:                            case Type.BYTE:
0232:                                mCurrentNode
0233:                                        .addInstruction(new TypesInstruction(
0234:                                                TypesOpcode.PUSH, CAT1_BYTE));
0235:                                break;
0236:                            case Type.CHAR:
0237:                                mCurrentNode
0238:                                        .addInstruction(new TypesInstruction(
0239:                                                TypesOpcode.PUSH, CAT1_CHAR));
0240:                                break;
0241:                            case Type.FLOAT:
0242:                                mCurrentNode
0243:                                        .addInstruction(new TypesInstruction(
0244:                                                TypesOpcode.PUSH, CAT1_FLOAT));
0245:                                break;
0246:                            case Type.INT:
0247:                                mCurrentNode
0248:                                        .addInstruction(new TypesInstruction(
0249:                                                TypesOpcode.PUSH, CAT1_INT));
0250:                                break;
0251:                            case Type.SHORT:
0252:                                mCurrentNode
0253:                                        .addInstruction(new TypesInstruction(
0254:                                                TypesOpcode.PUSH, CAT1_SHORT));
0255:                                break;
0256:                            case Type.DOUBLE:
0257:                                mCurrentNode
0258:                                        .addInstruction(new TypesInstruction(
0259:                                                TypesOpcode.PUSH, CAT2_DOUBLE));
0260:                                break;
0261:                            case Type.LONG:
0262:                                mCurrentNode
0263:                                        .addInstruction(new TypesInstruction(
0264:                                                TypesOpcode.PUSH, CAT2_LONG));
0265:                                break;
0266:                            }
0267:                        }
0268:                    }
0269:                }
0270:            }
0271:
0272:            /**
0273:             * Visits a type instruction. A type instruction is an instruction that
0274:             * takes a type descriptor as parameter.
0275:             *
0276:             * @param opcode the opcode of the type instruction to be visited. This opcode
0277:             *      is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
0278:             * @param desc the operand of the instruction to be visited. This operand is
0279:             *      must be a fully qualified class name in internal form, or the type
0280:             *      descriptor of an array type (see {@link Type Type}).
0281:             */
0282:            public void visitTypeInsn(int opcode, String desc) {
0283:                ///CLOVER:OFF
0284:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0285:                    ContinuationDebug.LOGGER
0286:                            .finest(" Type:visitTypeInsn           ("
0287:                                    + OPCODES[opcode] + ", \"" + desc + "\")");
0288:                ///CLOVER:ON
0289:
0290:                if (mCurrentNode != null) {
0291:                    switch (opcode) {
0292:                    case NEW:
0293:                        mCurrentNode.addInstruction(new TypesInstruction(
0294:                                TypesOpcode.PUSH, desc));
0295:                        break;
0296:                    case ANEWARRAY:
0297:                        mCurrentNode.addInstruction(new TypesInstruction(
0298:                                TypesOpcode.POP));
0299:                        // multi dims new arrays without final dimension specification
0300:                        // end up here as an array of arrays
0301:                        if (desc.startsWith("[")) {
0302:                            mCurrentNode.addInstruction(new TypesInstruction(
0303:                                    TypesOpcode.PUSH, "[" + desc));
0304:                        } else {
0305:                            mCurrentNode.addInstruction(new TypesInstruction(
0306:                                    TypesOpcode.PUSH, "[L" + desc + ";"));
0307:                        }
0308:                        break;
0309:                    case CHECKCAST:
0310:                        mCurrentNode.addInstruction(new TypesInstruction(
0311:                                TypesOpcode.POP));
0312:                        mCurrentNode.addInstruction(new TypesInstruction(
0313:                                TypesOpcode.PUSH, desc));
0314:                        break;
0315:                    case INSTANCEOF:
0316:                        mCurrentNode.addInstruction(new TypesInstruction(
0317:                                TypesOpcode.POP));
0318:                        mCurrentNode.addInstruction(new TypesInstruction(
0319:                                TypesOpcode.PUSH, desc));
0320:                        break;
0321:                    }
0322:                }
0323:            }
0324:
0325:            /**
0326:             * Visits a LDC instruction.
0327:             *
0328:             * @param cst the constant to be loaded on the stack. This parameter must be
0329:             *      a non null {@link java.lang.Integer Integer}, a {@link java.lang.Float
0330:             *      Float}, a {@link java.lang.Long Long}, a {@link java.lang.Double
0331:             *      Double} or a {@link String String}.
0332:             */
0333:            public void visitLdcInsn(Object cst) {
0334:                ///CLOVER:OFF
0335:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0336:                    ContinuationDebug.LOGGER
0337:                            .finest(" Type:visitLdcInsn            (" + cst
0338:                                    + ")");
0339:                ///CLOVER:ON
0340:
0341:                if (mCurrentNode != null) {
0342:                    mCurrentNode.addInstruction(new TypesInstruction(
0343:                            TypesOpcode.PUSH, Type.getInternalName(cst
0344:                                    .getClass())));
0345:                }
0346:            }
0347:
0348:            /**
0349:             * Visits a MULTIANEWARRAY instruction.
0350:             *
0351:             * @param desc an array type descriptor (see {@link Type Type}).
0352:             * @param dims number of dimensions of the array to allocate.
0353:             */
0354:            public void visitMultiANewArrayInsn(String desc, int dims) {
0355:                ///CLOVER:OFF
0356:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0357:                    ContinuationDebug.LOGGER
0358:                            .finest(" Type:visitMultiANewArrayInsn (\"" + desc
0359:                                    + "\", " + dims + ")");
0360:                ///CLOVER:ON
0361:
0362:                if (mCurrentNode != null) {
0363:                    for (int i = 1; i <= dims; i++) {
0364:                        mCurrentNode.addInstruction(new TypesInstruction(
0365:                                TypesOpcode.POP));
0366:                    }
0367:                    mCurrentNode.addInstruction(new TypesInstruction(
0368:                            TypesOpcode.PUSH, desc));
0369:                }
0370:            }
0371:
0372:            /**
0373:             * Visits a zero operand instruction.
0374:             *
0375:             * @param opcode the opcode of the instruction to be visited. This opcode is
0376:             *      either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
0377:             *      ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1,
0378:             *      FCONST_2, DCONST_0, DCONST_1,
0379:             *
0380:             *      IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
0381:             *      IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
0382:             *      SASTORE,
0383:             *
0384:             *      POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP,
0385:             *
0386:             *      IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL,
0387:             *      DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG,
0388:             *      FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR,
0389:             *      LOR, IXOR, LXOR,
0390:             *
0391:             *      I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C,
0392:             *      I2S,
0393:             *
0394:             *      LCMP, FCMPL, FCMPG, DCMPL, DCMPG,
0395:             *
0396:             *      IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN,
0397:             *
0398:             *      ARRAYLENGTH,
0399:             *
0400:             *      ATHROW,
0401:             *
0402:             *      MONITORENTER, or MONITOREXIT.
0403:             */
0404:            public void visitInsn(int opcode) {
0405:                ///CLOVER:OFF
0406:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0407:                    ContinuationDebug.LOGGER
0408:                            .finest(" Type:visitInsn               ("
0409:                                    + OPCODES[opcode] + ")");
0410:                ///CLOVER:ON
0411:
0412:                if (mCurrentNode != null) {
0413:                    switch (opcode) {
0414:                    case RETURN:
0415:                        mCurrentNode = null;
0416:                        break;
0417:                    case ATHROW:
0418:                        mCurrentNode.addInstruction(new TypesInstruction(
0419:                                TypesOpcode.POP));
0420:                        break;
0421:                    case ACONST_NULL:
0422:                        mCurrentNode.addInstruction(new TypesInstruction(
0423:                                TypesOpcode.PUSH, NULL));
0424:                        break;
0425:                    case ICONST_0:
0426:                    case ICONST_1:
0427:                    case ICONST_2:
0428:                    case ICONST_3:
0429:                    case ICONST_4:
0430:                    case ICONST_5:
0431:                    case ICONST_M1:
0432:                        mCurrentNode.addInstruction(new TypesInstruction(
0433:                                TypesOpcode.PUSH, CAT1_INT));
0434:                        break;
0435:                    case FCONST_0:
0436:                    case FCONST_1:
0437:                    case FCONST_2:
0438:                        mCurrentNode.addInstruction(new TypesInstruction(
0439:                                TypesOpcode.PUSH, CAT1_FLOAT));
0440:                        break;
0441:                    case LCONST_0:
0442:                    case LCONST_1:
0443:                        mCurrentNode.addInstruction(new TypesInstruction(
0444:                                TypesOpcode.PUSH, CAT2_LONG));
0445:                        break;
0446:                    case DCONST_0:
0447:                    case DCONST_1:
0448:                        mCurrentNode.addInstruction(new TypesInstruction(
0449:                                TypesOpcode.PUSH, CAT2_DOUBLE));
0450:                        break;
0451:                    case AALOAD:
0452:                        mCurrentNode.addInstruction(new TypesInstruction(
0453:                                TypesOpcode.AALOAD));
0454:                        break;
0455:                    case IALOAD:
0456:                        mCurrentNode.addInstruction(new TypesInstruction(
0457:                                TypesOpcode.POP));
0458:                        mCurrentNode.addInstruction(new TypesInstruction(
0459:                                TypesOpcode.POP));
0460:                        mCurrentNode.addInstruction(new TypesInstruction(
0461:                                TypesOpcode.PUSH, CAT1_INT));
0462:                        break;
0463:                    case FALOAD:
0464:                        mCurrentNode.addInstruction(new TypesInstruction(
0465:                                TypesOpcode.POP));
0466:                        mCurrentNode.addInstruction(new TypesInstruction(
0467:                                TypesOpcode.POP));
0468:                        mCurrentNode.addInstruction(new TypesInstruction(
0469:                                TypesOpcode.PUSH, CAT1_FLOAT));
0470:                        break;
0471:                    case BALOAD:
0472:                        mCurrentNode.addInstruction(new TypesInstruction(
0473:                                TypesOpcode.POP));
0474:                        mCurrentNode.addInstruction(new TypesInstruction(
0475:                                TypesOpcode.POP));
0476:                        mCurrentNode.addInstruction(new TypesInstruction(
0477:                                TypesOpcode.PUSH, CAT1_BYTE));
0478:                        break;
0479:                    case CALOAD:
0480:                        mCurrentNode.addInstruction(new TypesInstruction(
0481:                                TypesOpcode.POP));
0482:                        mCurrentNode.addInstruction(new TypesInstruction(
0483:                                TypesOpcode.POP));
0484:                        mCurrentNode.addInstruction(new TypesInstruction(
0485:                                TypesOpcode.PUSH, CAT1_CHAR));
0486:                        break;
0487:                    case SALOAD:
0488:                        mCurrentNode.addInstruction(new TypesInstruction(
0489:                                TypesOpcode.POP));
0490:                        mCurrentNode.addInstruction(new TypesInstruction(
0491:                                TypesOpcode.POP));
0492:                        mCurrentNode.addInstruction(new TypesInstruction(
0493:                                TypesOpcode.PUSH, CAT1_SHORT));
0494:                        break;
0495:                    case LALOAD:
0496:                        mCurrentNode.addInstruction(new TypesInstruction(
0497:                                TypesOpcode.POP));
0498:                        mCurrentNode.addInstruction(new TypesInstruction(
0499:                                TypesOpcode.POP));
0500:                        mCurrentNode.addInstruction(new TypesInstruction(
0501:                                TypesOpcode.PUSH, CAT2_LONG));
0502:                        break;
0503:                    case DALOAD:
0504:                        mCurrentNode.addInstruction(new TypesInstruction(
0505:                                TypesOpcode.POP));
0506:                        mCurrentNode.addInstruction(new TypesInstruction(
0507:                                TypesOpcode.POP));
0508:                        mCurrentNode.addInstruction(new TypesInstruction(
0509:                                TypesOpcode.PUSH, CAT2_DOUBLE));
0510:                        break;
0511:                    case IASTORE:
0512:                    case LASTORE:
0513:                    case FASTORE:
0514:                    case DASTORE:
0515:                    case AASTORE:
0516:                    case BASTORE:
0517:                    case CASTORE:
0518:                    case SASTORE:
0519:                        mCurrentNode.addInstruction(new TypesInstruction(
0520:                                TypesOpcode.POP));
0521:                        mCurrentNode.addInstruction(new TypesInstruction(
0522:                                TypesOpcode.POP));
0523:                        mCurrentNode.addInstruction(new TypesInstruction(
0524:                                TypesOpcode.POP));
0525:                        break;
0526:                    case POP:
0527:                        mCurrentNode.addInstruction(new TypesInstruction(
0528:                                TypesOpcode.POP));
0529:                        break;
0530:                    case POP2:
0531:                        mCurrentNode.addInstruction(new TypesInstruction(
0532:                                TypesOpcode.POP2));
0533:                        break;
0534:                    case DUP:
0535:                        mCurrentNode.addInstruction(new TypesInstruction(
0536:                                TypesOpcode.DUP));
0537:                        break;
0538:                    case DUP_X1:
0539:                        mCurrentNode.addInstruction(new TypesInstruction(
0540:                                TypesOpcode.DUPX1));
0541:                        break;
0542:                    case DUP_X2:
0543:                        mCurrentNode.addInstruction(new TypesInstruction(
0544:                                TypesOpcode.DUPX2));
0545:                        break;
0546:                    case DUP2:
0547:                        mCurrentNode.addInstruction(new TypesInstruction(
0548:                                TypesOpcode.DUP2));
0549:                        break;
0550:                    case DUP2_X1:
0551:                        mCurrentNode.addInstruction(new TypesInstruction(
0552:                                TypesOpcode.DUP2_X1));
0553:                        break;
0554:                    case DUP2_X2:
0555:                        mCurrentNode.addInstruction(new TypesInstruction(
0556:                                TypesOpcode.DUP2_X2));
0557:                        break;
0558:                    case SWAP:
0559:                        mCurrentNode.addInstruction(new TypesInstruction(
0560:                                TypesOpcode.SWAP));
0561:                        break;
0562:                    case IADD:
0563:                    case LADD:
0564:                    case FADD:
0565:                    case DADD:
0566:                    case ISUB:
0567:                    case LSUB:
0568:                    case FSUB:
0569:                    case DSUB:
0570:                    case IMUL:
0571:                    case LMUL:
0572:                    case FMUL:
0573:                    case DMUL:
0574:                    case IDIV:
0575:                    case LDIV:
0576:                    case FDIV:
0577:                    case DDIV:
0578:                    case IREM:
0579:                    case LREM:
0580:                    case FREM:
0581:                    case DREM:
0582:                    case ISHL:
0583:                    case LSHL:
0584:                    case ISHR:
0585:                    case LSHR:
0586:                    case IUSHR:
0587:                    case LUSHR:
0588:                    case IAND:
0589:                    case LAND:
0590:                    case IOR:
0591:                    case LOR:
0592:                    case IXOR:
0593:                    case LXOR:
0594:                        // just pop one type since the result is the same type as both operands
0595:                        mCurrentNode.addInstruction(new TypesInstruction(
0596:                                TypesOpcode.POP));
0597:                        break;
0598:                    case INEG:
0599:                    case LNEG:
0600:                    case FNEG:
0601:                    case DNEG:
0602:                        // do nothing, the type stack remains the same
0603:                        break;
0604:                    case I2F:
0605:                    case I2B:
0606:                    case I2C:
0607:                    case I2S:
0608:                    case L2D:
0609:                    case F2I:
0610:                    case D2L:
0611:                        // do nothing, the type stack remains the same
0612:                        break;
0613:                    case I2L:
0614:                    case F2L:
0615:                        // the type widens
0616:                        mCurrentNode.addInstruction(new TypesInstruction(
0617:                                TypesOpcode.POP));
0618:                        mCurrentNode.addInstruction(new TypesInstruction(
0619:                                TypesOpcode.PUSH, CAT2_LONG));
0620:                        break;
0621:                    case I2D:
0622:                    case F2D:
0623:                        // the type widens
0624:                        mCurrentNode.addInstruction(new TypesInstruction(
0625:                                TypesOpcode.POP));
0626:                        mCurrentNode.addInstruction(new TypesInstruction(
0627:                                TypesOpcode.PUSH, CAT2_DOUBLE));
0628:                        break;
0629:                    case L2I:
0630:                    case D2I:
0631:                        // the type shrinks
0632:                        mCurrentNode.addInstruction(new TypesInstruction(
0633:                                TypesOpcode.POP));
0634:                        mCurrentNode.addInstruction(new TypesInstruction(
0635:                                TypesOpcode.PUSH, CAT1_INT));
0636:                        break;
0637:                    case L2F:
0638:                    case D2F:
0639:                        // the type shrinks
0640:                        mCurrentNode.addInstruction(new TypesInstruction(
0641:                                TypesOpcode.POP));
0642:                        mCurrentNode.addInstruction(new TypesInstruction(
0643:                                TypesOpcode.PUSH, CAT1_FLOAT));
0644:                        break;
0645:                    case LCMP:
0646:                    case FCMPL:
0647:                    case FCMPG:
0648:                    case DCMPL:
0649:                    case DCMPG:
0650:                        mCurrentNode.addInstruction(new TypesInstruction(
0651:                                TypesOpcode.POP));
0652:                        mCurrentNode.addInstruction(new TypesInstruction(
0653:                                TypesOpcode.POP));
0654:                        mCurrentNode.addInstruction(new TypesInstruction(
0655:                                TypesOpcode.PUSH, CAT1_INT));
0656:                        break;
0657:                    case ARRAYLENGTH:
0658:                        mCurrentNode.addInstruction(new TypesInstruction(
0659:                                TypesOpcode.POP));
0660:                        mCurrentNode.addInstruction(new TypesInstruction(
0661:                                TypesOpcode.PUSH, CAT1_INT));
0662:                        break;
0663:                    case MONITORENTER:
0664:                    case MONITOREXIT:
0665:                        mCurrentNode.addInstruction(new TypesInstruction(
0666:                                TypesOpcode.POP));
0667:                        break;
0668:                    }
0669:                }
0670:            }
0671:
0672:            /**
0673:             * Visits an IINC instruction.
0674:             *
0675:             * @param var index of the local variable to be incremented.
0676:             * @param increment amount to increment the local variable by.
0677:             */
0678:            public void visitIincInsn(int var, int increment) {
0679:                ///CLOVER:OFF
0680:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0681:                    ContinuationDebug.LOGGER
0682:                            .finest(" Type:visitIincInsn           (" + var
0683:                                    + ", " + increment + ")");
0684:                ///CLOVER:ON
0685:
0686:                if (mCurrentNode != null) {
0687:                    mCurrentNode.addInstruction(new TypesInstruction(
0688:                            TypesOpcode.IINC, var));
0689:                }
0690:            }
0691:
0692:            /**
0693:             * Visits a field instruction. A field instruction is an instruction that
0694:             * loads or stores the value of a field of an object.
0695:             *
0696:             * @param opcode the opcode of the type instruction to be visited. This opcode
0697:             *      is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
0698:             * @param owner the internal name of the field's owner class (see {@link
0699:             *      Type#getInternalName getInternalName}).
0700:             * @param name the field's name.
0701:             * @param desc the field's descriptor (see {@link Type Type}).
0702:             */
0703:            public void visitFieldInsn(int opcode, String owner, String name,
0704:                    String desc) {
0705:                ///CLOVER:OFF
0706:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0707:                    ContinuationDebug.LOGGER
0708:                            .finest(" Type:visitFieldInsn          ("
0709:                                    + OPCODES[opcode] + ", \"" + owner
0710:                                    + "\", \"" + name + "\", \"" + desc + "\")");
0711:                ///CLOVER:ON
0712:
0713:                if (mCurrentNode != null) {
0714:                    switch (opcode) {
0715:                    case GETFIELD:
0716:                    case GETSTATIC: {
0717:                        // pop the object reference from the stack if it'd not a static
0718:                        // field access
0719:                        if (GETSTATIC != opcode) {
0720:                            mCurrentNode.addInstruction(new TypesInstruction(
0721:                                    TypesOpcode.POP));
0722:                        }
0723:
0724:                        Type type = Type.getType(desc);
0725:                        switch (type.getSort()) {
0726:                        case Type.OBJECT:
0727:                            mCurrentNode.addInstruction(new TypesInstruction(
0728:                                    TypesOpcode.PUSH, type.getInternalName()));
0729:                            break;
0730:                        case Type.ARRAY:
0731:                            mCurrentNode.addInstruction(new TypesInstruction(
0732:                                    TypesOpcode.PUSH, type.getDescriptor()));
0733:                            break;
0734:                        case Type.BOOLEAN:
0735:                            mCurrentNode.addInstruction(new TypesInstruction(
0736:                                    TypesOpcode.PUSH, CAT1_BOOLEAN));
0737:                            break;
0738:                        case Type.BYTE:
0739:                            mCurrentNode.addInstruction(new TypesInstruction(
0740:                                    TypesOpcode.PUSH, CAT1_BYTE));
0741:                            break;
0742:                        case Type.CHAR:
0743:                            mCurrentNode.addInstruction(new TypesInstruction(
0744:                                    TypesOpcode.PUSH, CAT1_CHAR));
0745:                            break;
0746:                        case Type.FLOAT:
0747:                            mCurrentNode.addInstruction(new TypesInstruction(
0748:                                    TypesOpcode.PUSH, CAT1_FLOAT));
0749:                            break;
0750:                        case Type.INT:
0751:                            mCurrentNode.addInstruction(new TypesInstruction(
0752:                                    TypesOpcode.PUSH, CAT1_INT));
0753:                            break;
0754:                        case Type.SHORT:
0755:                            mCurrentNode.addInstruction(new TypesInstruction(
0756:                                    TypesOpcode.PUSH, CAT1_SHORT));
0757:                            break;
0758:                        case Type.DOUBLE:
0759:                            mCurrentNode.addInstruction(new TypesInstruction(
0760:                                    TypesOpcode.PUSH, CAT2_DOUBLE));
0761:                            break;
0762:                        case Type.LONG:
0763:                            mCurrentNode.addInstruction(new TypesInstruction(
0764:                                    TypesOpcode.PUSH, CAT2_LONG));
0765:                            break;
0766:                        }
0767:                    }
0768:
0769:                        break;
0770:                    case PUTFIELD:
0771:                    case PUTSTATIC:
0772:                        mCurrentNode.addInstruction(new TypesInstruction(
0773:                                TypesOpcode.POP));
0774:
0775:                        // pop the object reference from the stack if it'd not a static
0776:                        // field access
0777:                        if (GETSTATIC != opcode) {
0778:                            mCurrentNode.addInstruction(new TypesInstruction(
0779:                                    TypesOpcode.POP));
0780:                        }
0781:
0782:                        break;
0783:                    }
0784:                }
0785:            }
0786:
0787:            /**
0788:             * Visits an instruction with a single int operand.
0789:             *
0790:             * @param opcode the opcode of the instruction to be visited. This opcode is
0791:             *      either BIPUSH, SIPUSH or NEWARRAY.
0792:             * @param operand the operand of the instruction to be visited.
0793:             */
0794:            public void visitIntInsn(int opcode, int operand) {
0795:                ///CLOVER:OFF
0796:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0797:                    ContinuationDebug.LOGGER
0798:                            .finest(" Type:visitIntInsn            ("
0799:                                    + OPCODES[opcode] + ", " + operand + ")");
0800:                ///CLOVER:ON
0801:
0802:                if (mCurrentNode != null) {
0803:                    switch (opcode) {
0804:                    case BIPUSH:
0805:                        mCurrentNode.addInstruction(new TypesInstruction(
0806:                                TypesOpcode.PUSH, CAT1_BYTE));
0807:                        break;
0808:                    case SIPUSH:
0809:                        mCurrentNode.addInstruction(new TypesInstruction(
0810:                                TypesOpcode.PUSH, CAT1_SHORT));
0811:                        break;
0812:                    case NEWARRAY:
0813:                        mCurrentNode.addInstruction(new TypesInstruction(
0814:                                TypesOpcode.POP));
0815:                        switch (operand) {
0816:                        case T_BOOLEAN:
0817:                            mCurrentNode.addInstruction(new TypesInstruction(
0818:                                    TypesOpcode.PUSH, ARRAY_BOOLEAN));
0819:                            break;
0820:                        case T_CHAR:
0821:                            mCurrentNode.addInstruction(new TypesInstruction(
0822:                                    TypesOpcode.PUSH, ARRAY_CHAR));
0823:                            break;
0824:                        case T_FLOAT:
0825:                            mCurrentNode.addInstruction(new TypesInstruction(
0826:                                    TypesOpcode.PUSH, ARRAY_FLOAT));
0827:                            break;
0828:                        case T_DOUBLE:
0829:                            mCurrentNode.addInstruction(new TypesInstruction(
0830:                                    TypesOpcode.PUSH, ARRAY_DOUBLE));
0831:                            break;
0832:                        case T_BYTE:
0833:                            mCurrentNode.addInstruction(new TypesInstruction(
0834:                                    TypesOpcode.PUSH, ARRAY_BYTE));
0835:                            break;
0836:                        case T_SHORT:
0837:                            mCurrentNode.addInstruction(new TypesInstruction(
0838:                                    TypesOpcode.PUSH, ARRAY_SHORT));
0839:                            break;
0840:                        case T_INT:
0841:                            mCurrentNode.addInstruction(new TypesInstruction(
0842:                                    TypesOpcode.PUSH, ARRAY_INT));
0843:                            break;
0844:                        case T_LONG:
0845:                            mCurrentNode.addInstruction(new TypesInstruction(
0846:                                    TypesOpcode.PUSH, ARRAY_LONG));
0847:                            break;
0848:                        }
0849:                        break;
0850:                    }
0851:                }
0852:            }
0853:
0854:            /**
0855:             * Visits a try catch block.
0856:             *
0857:             * @param start beginning of the exception handler's scope (inclusive).
0858:             * @param end end of the exception handler's scope (exclusive).
0859:             * @param handler beginning of the exception handler's code.
0860:             * @param type internal name of the type of exceptions handled by the handler,
0861:             *      or <tt>null</tt> to catch any exceptions (for "finally" blocks).
0862:             * @throws IllegalArgumentException if one of the labels has not already been
0863:             *      visited by this visitor (by the {@link #visitLabel visitLabel}
0864:             *      method).
0865:             */
0866:            public void visitTryCatchBlock(Label start, Label end,
0867:                    Label handler, String type) {
0868:                ///CLOVER:OFF
0869:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0870:                    ContinuationDebug.LOGGER
0871:                            .finest(" Code:visitTryCatchBlock      (" + start
0872:                                    + ", " + end + ", " + handler + ", \""
0873:                                    + type + "\")");
0874:                ///CLOVER:ON
0875:
0876:                List<Label> handlers = mTryCatchHandlers.get(start);
0877:                if (null == handlers) {
0878:                    handlers = new ArrayList<Label>();
0879:                    mTryCatchHandlers.put(start, handlers);
0880:                }
0881:
0882:                handlers.add(handler);
0883:            }
0884:
0885:            /**
0886:             * Visits a LOOKUPSWITCH instruction.
0887:             *
0888:             * @param dflt beginning of the default handler block.
0889:             * @param keys the values of the keys.
0890:             * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
0891:             *      beginning of the handler block for the <tt>keys[i]</tt> key.
0892:             */
0893:            public void visitLookupSwitchInsn(Label dflt, int[] keys,
0894:                    Label[] labels) {
0895:                ///CLOVER:OFF
0896:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0897:                    ContinuationDebug.LOGGER
0898:                            .finest(" Type:visitLookupSwitchInsn   ("
0899:                                    + dflt
0900:                                    + ", "
0901:                                    + (null == keys ? null : join(keys, ","))
0902:                                    + ", "
0903:                                    + (null == labels ? null
0904:                                            : join(labels, ",")) + ")");
0905:                ///CLOVER:ON
0906:
0907:                if (mCurrentNode != null) {
0908:                    mCurrentNode.addInstruction(new TypesInstruction(
0909:                            TypesOpcode.POP));
0910:
0911:                    // add all the switch's successors
0912:                    mCurrentNode.addSuccessor(dflt);
0913:                    for (int i = 0; i < labels.length; ++i) {
0914:                        mCurrentNode.addSuccessor(labels[i]);
0915:                    }
0916:
0917:                    // end the current node
0918:                    mCurrentNode = null;
0919:                }
0920:            }
0921:
0922:            /**
0923:             * Visits a jump instruction. A jump instruction is an instruction that may
0924:             * jump to another instruction.
0925:             *
0926:             * @param opcode the opcode of the type instruction to be visited. This opcode
0927:             *      is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE,
0928:             *      IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE,
0929:             *      GOTO, JSR, IFNULL or IFNONNULL.
0930:             * @param label the operand of the instruction to be visited. This operand is
0931:             *      a label that designates the instruction to which the jump instruction
0932:             *      may jump.
0933:             */
0934:            public void visitJumpInsn(int opcode, Label label) {
0935:                ///CLOVER:OFF
0936:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0937:                    ContinuationDebug.LOGGER
0938:                            .finest(" Type:visitJumpInsn           ("
0939:                                    + OPCODES[opcode] + ", " + label + ")");
0940:                ///CLOVER:ON
0941:
0942:                if (mCurrentNode != null) {
0943:                    switch (opcode) {
0944:                    case IFEQ:
0945:                    case IFNE:
0946:                    case IFLT:
0947:                    case IFGE:
0948:                    case IFGT:
0949:                    case IFLE:
0950:                    case IFNULL:
0951:                    case IFNONNULL:
0952:                        mCurrentNode.addInstruction(new TypesInstruction(
0953:                                TypesOpcode.POP));
0954:                        mCurrentNode.addSuccessor(label);
0955:                        break;
0956:                    case IF_ICMPEQ:
0957:                    case IF_ICMPNE:
0958:                    case IF_ICMPLT:
0959:                    case IF_ICMPGE:
0960:                    case IF_ICMPGT:
0961:                    case IF_ICMPLE:
0962:                    case IF_ACMPEQ:
0963:                    case IF_ACMPNE:
0964:                        mCurrentNode.addInstruction(new TypesInstruction(
0965:                                TypesOpcode.POP));
0966:                        mCurrentNode.addInstruction(new TypesInstruction(
0967:                                TypesOpcode.POP));
0968:                        mCurrentNode.addSuccessor(label);
0969:                        break;
0970:                    case JSR:
0971:                        mCurrentNode.addInstruction(new TypesInstruction(
0972:                                TypesOpcode.PUSH, CAT1_ADDRESS));
0973:                        mCurrentNode.addSuccessor(label);
0974:                        break;
0975:                    case GOTO:
0976:                        mCurrentNode.addSuccessor(label);
0977:
0978:                        // end the current node
0979:                        mCurrentNode = null;
0980:                        break;
0981:                    }
0982:                }
0983:            }
0984:
0985:            /**
0986:             * Visits a label. A label designates the instruction that will be visited
0987:             * just after it.
0988:             *
0989:             * @param label a {@link Label Label} object.
0990:             */
0991:            public void visitLabel(Label label) {
0992:                ///CLOVER:OFF
0993:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0994:                    ContinuationDebug.LOGGER
0995:                            .finest(" Type:visitLabel              (" + label
0996:                                    + ")");
0997:                ///CLOVER:ON
0998:
0999:                // begins a new current block
1000:                TypesNode new_node = new TypesNode();
1001:                mLabelMapping.put(label, new_node);
1002:
1003:                if (mCurrentNode != null) {
1004:                    mCurrentNode.setFollowingNode(new_node);
1005:                }
1006:                mCurrentNode = new_node;
1007:
1008:                mCurrentNode.addInstruction(new TypesInstruction(
1009:                        TypesOpcode.LABEL, ++mLabelcount));
1010:
1011:                // if the label starts with an exception type, change the sort of
1012:                // the created node and add the exception type as the the first type
1013:                // on the stack
1014:                String exception_type = mClassVisitor.getMetrics()
1015:                        .nextExceptionType();
1016:                if (exception_type != null) {
1017:                    mCurrentNode.setSort(TypesNode.EXCEPTION);
1018:                    mCurrentNode.addInstruction(new TypesInstruction(
1019:                            TypesOpcode.PUSH, exception_type));
1020:                }
1021:            }
1022:
1023:            /**
1024:             * Visits a TABLESWITCH instruction.
1025:             *
1026:             * @param min the minimum key value.
1027:             * @param max the maximum key value.
1028:             * @param dflt beginning of the default handler block.
1029:             * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
1030:             *      beginning of the handler block for the <tt>min + i</tt> key.
1031:             */
1032:            public void visitTableSwitchInsn(int min, int max, Label dflt,
1033:                    Label[] labels) {
1034:                ///CLOVER:OFF
1035:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1036:                    ContinuationDebug.LOGGER
1037:                            .finest(" Code:visitTableSwitchInsn    ("
1038:                                    + min
1039:                                    + ", "
1040:                                    + max
1041:                                    + ", "
1042:                                    + dflt
1043:                                    + ", "
1044:                                    + (null == labels ? null
1045:                                            : join(labels, ",")) + ")");
1046:                ///CLOVER:ON
1047:
1048:                if (mCurrentNode != null) {
1049:                    mCurrentNode.addInstruction(new TypesInstruction(
1050:                            TypesOpcode.POP));
1051:
1052:                    // add all the switch's successors
1053:                    mCurrentNode.addSuccessor(dflt);
1054:                    for (int i = 0; i < labels.length; ++i) {
1055:                        mCurrentNode.addSuccessor(labels[i]);
1056:                    }
1057:
1058:                    // end the current node
1059:                    mCurrentNode = null;
1060:                }
1061:            }
1062:
1063:            /**
1064:             * Visits the maximum stack size and the maximum number of local variables of
1065:             * the method.
1066:             *
1067:             * @param maxStack maximum stack size of the method.
1068:             * @param maxLocals maximum number of local variables for the method.
1069:             */
1070:            public void visitMaxs(int maxStack, int maxLocals) {
1071:                ///CLOVER:OFF
1072:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1073:                    ContinuationDebug.LOGGER
1074:                            .finest("\nPROCESSING CONTROL FLOW");
1075:                ///CLOVER:ON
1076:
1077:                // process all try-catch instructions and map the start labels to their
1078:                // handler successor
1079:                for (Map.Entry<Label, List<Label>> entry : mTryCatchHandlers
1080:                        .entrySet()) {
1081:                    TypesNode try_node = mLabelMapping.get(entry.getKey());
1082:                    if (try_node != null) {
1083:                        for (Label handler : entry.getValue()) {
1084:                            try_node.addSuccessor(handler);
1085:                        }
1086:                    }
1087:                }
1088:
1089:                // start the control flow analysis
1090:                mPauseContexts = new TypesContext[mPausecount + 1];
1091:                mLabelContexts = new TypesContext[mLabelcount + 1];
1092:
1093:                TypesNode following_node = null;
1094:                TypesNode successor_node = null;
1095:
1096:                // control flow analysis algorithm
1097:                TypesNode stack = mRootNode;
1098:                while (stack != null) {
1099:                    // pops a block from the stack
1100:                    TypesNode node = stack;
1101:                    stack = stack.getNextToProcess();
1102:
1103:                    // process the node's instructions
1104:                    processInstructions(node);
1105:
1106:                    // analyzes the node's successors
1107:                    TypesSuccessor successor = node.getSuccessors();
1108:                    while (successor != null) {
1109:                        successor_node = mLabelMapping
1110:                                .get(successor.getLabel());
1111:
1112:                        if (!successor_node.isProcessed()) {
1113:                            successor_node.setProcessed(true);
1114:                            successor_node.setPreceeder(true, node);
1115:
1116:                            // push the previous node on the stack
1117:                            successor_node.setNextToProcess(stack);
1118:                            stack = successor_node;
1119:                        }
1120:
1121:                        // iterate through the successors
1122:                        successor = successor.getNextSuccessor();
1123:                    }
1124:                    // handle a possible following node
1125:                    if (node.getFollowingNode() != null
1126:                            && !node.getFollowingNode().isProcessed()) {
1127:                        following_node = node.getFollowingNode();
1128:
1129:                        following_node.setProcessed(true);
1130:                        following_node.setPreceeder(false, node);
1131:
1132:                        // push the previous node on the stack
1133:                        following_node.setNextToProcess(stack);
1134:                        stack = following_node;
1135:                    }
1136:                }
1137:
1138:                mClassVisitor.setPauseContexts(mPauseContexts);
1139:                mClassVisitor.setLabelContexts(mLabelContexts);
1140:            }
1141:
1142:            private void processInstructions(TypesNode node) {
1143:                // setup the context for the node
1144:                TypesContext context = null;
1145:                // if it's the first node, create a new context
1146:                if (null == node.getPreceeder()) {
1147:                    context = new TypesContext();
1148:                }
1149:                // otherwise retrieve the previous context
1150:                else {
1151:                    TypesContext preceeder_context = node.getPreceeder()
1152:                            .getContext();
1153:                    // always isolate the context for a successor
1154:                    if (node.getIsSuccessor()) {
1155:                        context = preceeder_context.clone();
1156:                    } else {
1157:                        context = new TypesContext(preceeder_context.getVars(),
1158:                                preceeder_context.getStackClone());
1159:                    }
1160:                }
1161:                node.setContext(context);
1162:
1163:                ///CLOVER:OFF
1164:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1165:                    context.setDebugIndent(repeat("  ", node.getLevel()));
1166:                ///CLOVER:ON
1167:
1168:                TypesContext exception_context = null;
1169:                for (TypesInstruction instruction : node.getInstructions()) {
1170:                    switch (instruction.getOpcode()) {
1171:                    case TypesOpcode.SET: {
1172:                        String type = context.peek();
1173:                        if (instruction.getType() != null) {
1174:                            type = instruction.getType();
1175:                        }
1176:
1177:                        // if the variables types in the scope change or if a new var is added,
1178:                        // ensure that the context vars are isolated
1179:                        String current_var_type = context.getVar(instruction
1180:                                .getArgument());
1181:                        if (node.getPreceeder() != null
1182:                                && context.getVars() == node.getPreceeder()
1183:                                        .getContext().getVars()
1184:                                && (null == current_var_type || (current_var_type != TypesContext.NULL && !current_var_type
1185:                                        .equals(type)))) {
1186:                            context.cloneVars();
1187:                        }
1188:
1189:                        ///CLOVER:OFF
1190:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1191:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1192:                                    .getLevel())
1193:                                    + "  SET  "
1194:                                    + instruction.getArgument()
1195:                                    + ", " + type);
1196:                        ///CLOVER:ON
1197:
1198:                        context.pop();
1199:                        context.setVar(instruction.getArgument(), type);
1200:                        if (exception_context != null) {
1201:                            exception_context.setVar(instruction.getArgument(),
1202:                                    type);
1203:                            exception_context = null;
1204:                        }
1205:                    }
1206:                        break;
1207:                    case TypesOpcode.GET: {
1208:                        String type = instruction.getType();
1209:                        if (null == type) {
1210:                            type = context.getVar(instruction.getArgument());
1211:                        }
1212:
1213:                        ///CLOVER:OFF
1214:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1215:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1216:                                    .getLevel())
1217:                                    + "  GET  "
1218:                                    + instruction.getArgument()
1219:                                    + ", " + type);
1220:                        ///CLOVER:ON
1221:
1222:                        context.push(type);
1223:                    }
1224:                        break;
1225:                    case TypesOpcode.IINC:
1226:                        // do nothing
1227:                        break;
1228:                    case TypesOpcode.POP: {
1229:                        ///CLOVER:OFF
1230:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1231:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1232:                                    .getLevel())
1233:                                    + "  POP " + context.peek());
1234:                        ///CLOVER:ON
1235:
1236:                        context.pop();
1237:                    }
1238:                        break;
1239:                    case TypesOpcode.POP2: {
1240:                        ///CLOVER:OFF
1241:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1242:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1243:                                    .getLevel())
1244:                                    + "  POP2 " + context.peek());
1245:                        ///CLOVER:ON
1246:
1247:                        String type = context.pop();
1248:                        if (!type.startsWith("2")) {
1249:                            context.pop();
1250:                        }
1251:                    }
1252:                        break;
1253:                    case TypesOpcode.PUSH:
1254:                        ///CLOVER:OFF
1255:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1256:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1257:                                    .getLevel())
1258:                                    + "  PUSH " + instruction.getType());
1259:                        ///CLOVER:ON
1260:
1261:                        context.push(instruction.getType());
1262:                        break;
1263:                    case TypesOpcode.AALOAD: {
1264:                        context.pop();
1265:                        String array_desc = context.pop();
1266:                        String element_desc = null;
1267:                        if (array_desc.startsWith("[[")) {
1268:                            element_desc = array_desc.substring(1);
1269:                        } else {
1270:                            Type array_type = Type.getType(array_desc);
1271:                            element_desc = array_type.getElementType()
1272:                                    .getInternalName();
1273:                        }
1274:
1275:                        context.push(element_desc);
1276:                    }
1277:                        break;
1278:                    case TypesOpcode.DUP:
1279:                        context.push(context.peek());
1280:                        break;
1281:                    case TypesOpcode.DUPX1: {
1282:                        String type1 = context.pop();
1283:                        String type2 = context.pop();
1284:                        context.push(type1);
1285:                        context.push(type2);
1286:                        context.push(type1);
1287:                    }
1288:                        break;
1289:                    case TypesOpcode.DUPX2: {
1290:                        String type1 = context.pop();
1291:                        String type2 = context.pop();
1292:                        if (type2.startsWith("2")) {
1293:                            context.push(type1);
1294:                            context.push(type2);
1295:                            context.push(type1);
1296:                        } else {
1297:                            String type3 = context.pop();
1298:                            if (type3 != null) {
1299:                                context.push(type1);
1300:                                context.push(type3);
1301:                                context.push(type2);
1302:                                context.push(type1);
1303:                            }
1304:                        }
1305:                    }
1306:                        break;
1307:                    case TypesOpcode.DUP2: {
1308:                        String type1 = context.pop();
1309:                        if (type1.startsWith("2")) {
1310:                            context.push(type1);
1311:                            context.push(type1);
1312:                        } else {
1313:                            String type2 = context.pop();
1314:                            context.push(type2);
1315:                            context.push(type1);
1316:                            context.push(type2);
1317:                            context.push(type1);
1318:                        }
1319:                    }
1320:                        break;
1321:                    case TypesOpcode.DUP2_X1: {
1322:                        String type1 = context.pop();
1323:                        String type2 = context.pop();
1324:                        if (type1.startsWith("2")) {
1325:                            context.push(type1);
1326:                            context.push(type2);
1327:                            context.push(type1);
1328:                        } else {
1329:                            String type3 = context.pop();
1330:                            context.push(type2);
1331:                            context.push(type1);
1332:                            context.push(type3);
1333:                            context.push(type2);
1334:                            context.push(type1);
1335:                        }
1336:                    }
1337:                        break;
1338:                    case TypesOpcode.DUP2_X2: {
1339:                        String type1 = context.pop();
1340:                        String type2 = context.pop();
1341:                        if (type1.startsWith("2")) {
1342:                            if (type2.startsWith("2")) // form 4
1343:                            {
1344:                                context.push(type1);
1345:                                context.push(type2);
1346:                                context.push(type1);
1347:                            } else // form 2
1348:                            {
1349:                                String type3 = context.pop();
1350:                                context.push(type1);
1351:                                context.push(type3);
1352:                                context.push(type2);
1353:                                context.push(type1);
1354:                            }
1355:                        } else if (!type2.startsWith("2")) {
1356:                            String type3 = context.pop();
1357:                            if (type3.startsWith("2")) // form 3
1358:                            {
1359:                                context.push(type2);
1360:                                context.push(type1);
1361:                                context.push(type3);
1362:                                context.push(type2);
1363:                                context.push(type1);
1364:                            } else // form 1
1365:                            {
1366:                                String type4 = context.pop();
1367:                                context.push(type2);
1368:                                context.push(type1);
1369:                                context.push(type4);
1370:                                context.push(type3);
1371:                                context.push(type2);
1372:                                context.push(type1);
1373:                            }
1374:                        }
1375:                    }
1376:                        break;
1377:                    case TypesOpcode.SWAP: {
1378:                        String type1 = context.pop();
1379:                        String type2 = context.pop();
1380:                        context.push(type1);
1381:                        context.push(type2);
1382:                    }
1383:                        break;
1384:                    case TypesOpcode.PAUSE:
1385:                        ///CLOVER:OFF
1386:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1387:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1388:                                    .getLevel())
1389:                                    + "PAUSE " + instruction.getArgument());
1390:                        ///CLOVER:ON
1391:
1392:                        mPauseContexts[instruction.getArgument()] = context
1393:                                .clone(node);
1394:                        break;
1395:                    case TypesOpcode.LABEL: {
1396:                        ///CLOVER:OFF
1397:                        if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1398:                            ContinuationDebug.LOGGER.finest(repeat("  ", node
1399:                                    .getLevel())
1400:                                    + "LABEL " + instruction.getArgument());
1401:                        ///CLOVER:ON
1402:
1403:                        TypesContext label_context = context.clone(node);
1404:                        mLabelContexts[instruction.getArgument()] = label_context;
1405:                        if (TypesNode.EXCEPTION == node.getSort()) {
1406:                            exception_context = label_context;
1407:                        }
1408:                    }
1409:                        break;
1410:                    }
1411:                }
1412:            }
1413:
1414:            /**
1415:             * Visits a line number declaration.
1416:             *
1417:             * @param line a line number. This number refers to the source file
1418:             *      from which the class was compiled.
1419:             * @param start the first instruction corresponding to this line number.
1420:             * @throws IllegalArgumentException if <tt>start</tt> has not already been
1421:             *      visited by this visitor (by the {@link #visitLabel visitLabel}
1422:             *      method).
1423:             */
1424:            public void visitLineNumber(int line, Label start) {
1425:                ///CLOVER:OFF
1426:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1427:                    ContinuationDebug.LOGGER
1428:                            .finest(" Type:visitLineNumber         (" + line
1429:                                    + ", " + start + ")");
1430:                ///CLOVER:ON
1431:            }
1432:
1433:            /**
1434:             * Visits a local variable declaration.
1435:             *
1436:             * @param name the name of a local variable.
1437:             * @param desc the type descriptor of this local variable.
1438:             * @param signature the type signature of this local variable. May be
1439:             *      <tt>null</tt> if the local variable type does not use generic types.
1440:             * @param start the first instruction corresponding to the scope of this
1441:             *      local variable (inclusive).
1442:             * @param end the last instruction corresponding to the scope of this
1443:             *      local variable (exclusive).
1444:             * @param index the local variable's index.
1445:             * @throws IllegalArgumentException if one of the labels has not already been
1446:             *      visited by this visitor (by the {@link #visitLabel visitLabel}
1447:             *      method).
1448:             */
1449:            public void visitLocalVariable(String name, String desc,
1450:                    String signature, Label start, Label end, int index) {
1451:                ///CLOVER:OFF
1452:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1453:                    ContinuationDebug.LOGGER
1454:                            .finest(" Type:visitLocalVariable      (\"" + name
1455:                                    + "\", \"" + desc + "\", \"" + signature
1456:                                    + "\", " + start + ", " + end + ", "
1457:                                    + index + ")");
1458:                ///CLOVER:ON
1459:            }
1460:
1461:            /**
1462:             * Visits a non standard attribute of the code. This method must visit only
1463:             * the first attribute in the given attribute list.
1464:             *
1465:             * @param attr a non standard code attribute. Must not be <tt>null</tt>.
1466:             */
1467:            public void visitAttribute(Attribute attr) {
1468:                ///CLOVER:OFF
1469:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1470:                    ContinuationDebug.LOGGER
1471:                            .finest(" Type:visitAttribute          (" + attr
1472:                                    + ")");
1473:                ///CLOVER:ON
1474:            }
1475:
1476:            public void visitCode() {
1477:                ///CLOVER:OFF
1478:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1479:                    ContinuationDebug.LOGGER
1480:                            .finest(" Code:visitCode               ()");
1481:                ///CLOVER:ON
1482:            }
1483:
1484:            /**
1485:             * Visits the default value of this annotation interface method.
1486:             *
1487:             * @return a visitor to the visit the actual default value of this annotation
1488:             *      interface method. The 'name' parameters passed to the methods of this
1489:             *      annotation visitor are ignored. Moreover, exacly one visit method
1490:             *      must be called on this annotation visitor, followed by visitEnd.
1491:             */
1492:            public AnnotationVisitor visitAnnotationDefault() {
1493:                ///CLOVER:OFF
1494:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1495:                    ContinuationDebug.LOGGER
1496:                            .finest(" Type:visitAnnotationDefault  ()");
1497:                ///CLOVER:ON
1498:
1499:                return mAnnotationVisitor;
1500:            }
1501:
1502:            /**
1503:             * Visits an annotation of this method.
1504:             *
1505:             * @param desc the class descriptor of the annotation class.
1506:             * @param visible <tt>true</tt> if the annotation is visible at runtime.
1507:             * @return a visitor to visit the annotation values.
1508:             */
1509:            public AnnotationVisitor visitAnnotation(String desc,
1510:                    boolean visible) {
1511:                ///CLOVER:OFF
1512:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1513:                    ContinuationDebug.LOGGER
1514:                            .finest(" Type:visitAnnotation         (\"" + desc
1515:                                    + "\", " + visible + ")");
1516:                ///CLOVER:ON
1517:
1518:                return mAnnotationVisitor;
1519:            }
1520:
1521:            /**
1522:             * Visits an annotation of a parameter this method.
1523:             *
1524:             * @param parameter the parameter index.
1525:             * @param desc the class descriptor of the annotation class.
1526:             * @param visible <tt>true</tt> if the annotation is visible at runtime.
1527:             * @return a visitor to visit the annotation values.
1528:             */
1529:            public AnnotationVisitor visitParameterAnnotation(int parameter,
1530:                    String desc, boolean visible) {
1531:                ///CLOVER:OFF
1532:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1533:                    ContinuationDebug.LOGGER
1534:                            .finest(" Type:visitParameterAnnotation("
1535:                                    + parameter + ", \"" + desc + "\", "
1536:                                    + visible + ")");
1537:                ///CLOVER:ON
1538:
1539:                return mAnnotationVisitor;
1540:            }
1541:
1542:            /**
1543:             * Visits the end of the method. This method, which is the last one to be
1544:             * called, is used to inform the visitor that all the annotations and
1545:             * attributes of the method have been visited.
1546:             */
1547:            public void visitEnd() {
1548:                ///CLOVER:OFF
1549:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1550:                    ContinuationDebug.LOGGER
1551:                            .finest(" Type:visitEnd                ()");
1552:                ///CLOVER:ON
1553:            }
1554:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.