Source Code Cross Referenced for ResumableMethodAdapter.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: ResumableMethodAdapter.java 3850 2007-07-12 18:46:42Z 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 java.util.Stack;
0014:        import java.util.logging.Level;
0015:
0016:        import static com.uwyn.rife.continuations.instrument.ContinuationDebug.*;
0017:        import static com.uwyn.rife.continuations.instrument.TypesContext.*;
0018:
0019:        class ResumableMethodAdapter implements  MethodVisitor, Opcodes {
0020:            private ContinuationConfigInstrument mConfig = null;
0021:
0022:            private TypesClassVisitor mTypes = null;
0023:
0024:            private MethodVisitor mMethodVisitor = null;
0025:            private String mClassName = null;
0026:            private String mClassNameInternal = null;
0027:            private boolean mVisit = false;
0028:            private boolean mAdapt = false;
0029:            private int mContextIndex = -1;
0030:            private int mCallTargetIndex = -1;
0031:            private int mAnswerIndex = -1;
0032:            private int mTempIndex = -1;
0033:
0034:            private Label mDefaultLabel = null;
0035:            private Label mRethrowLabel = null;
0036:            private boolean mUseRethrowLabel = false;
0037:            private Label[] mLabels = null;
0038:            private int mLabelIndex = 0;
0039:
0040:            private int mMaxLocalIndex = 0;
0041:
0042:            private TypesContext mLabelContext = null;
0043:
0044:            private boolean mDisableCodeguideBackInTime = false;
0045:            private boolean mDisabledCodeguideBackInTime = false;
0046:
0047:            private NoOpAnnotationVisitor mAnnotationVisitor = new NoOpAnnotationVisitor();
0048:
0049:            private void debugMessage(String message) {
0050:                if (ContinuationDebug.sTrace
0051:                        && ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) {
0052:                    mMethodVisitor.visitFieldInsn(GETSTATIC,
0053:                            "com/uwyn/rife/continuations/ContinuationDebug",
0054:                            "LOGGER", "Ljava/util/logging/Logger;");
0055:                    mMethodVisitor.visitLdcInsn(message);
0056:                    mMethodVisitor.visitMethodInsn(INVOKEVIRTUAL,
0057:                            "java/util/logging/Logger", "finest",
0058:                            "(Ljava/lang/String;)V");
0059:                }
0060:            }
0061:
0062:            ResumableMethodAdapter(ContinuationConfigInstrument config,
0063:                    TypesClassVisitor types, MethodVisitor methodVisitor,
0064:                    String className, boolean adapt, int maxLocals,
0065:                    int pauseCount) {
0066:                mConfig = config;
0067:                mTypes = types;
0068:                mMethodVisitor = methodVisitor;
0069:                mClassName = className;
0070:                if (className != null) {
0071:                    mClassNameInternal = mClassName.replace('.', '/');
0072:                }
0073:                mVisit = (mMethodVisitor != null);
0074:                mAdapt = adapt;
0075:                mContextIndex = maxLocals;
0076:                mCallTargetIndex = mContextIndex + 1;
0077:                mAnswerIndex = mCallTargetIndex + 1;
0078:                mTempIndex = mAnswerIndex + 1;
0079:
0080:                if (mAdapt) {
0081:                    if (pauseCount > 0) {
0082:                        // create all the labels beforehand
0083:                        mDefaultLabel = new Label();
0084:                        mRethrowLabel = new Label();
0085:                        mLabels = new Label[pauseCount];
0086:                        for (int i = 0; i < pauseCount; i++) {
0087:                            mLabels[i] = new Label();
0088:                        }
0089:                    }
0090:
0091:                    debugMessage("CONT: context initializing");
0092:                    // get the current context for the current method and register it
0093:                    // after the last local variable
0094:                    mMethodVisitor.visitVarInsn(ALOAD, 0);
0095:                    mMethodVisitor
0096:                            .visitMethodInsn(
0097:                                    INVOKESTATIC,
0098:                                    "com/uwyn/rife/continuations/ContinuationContext",
0099:                                    "createOrResetContext",
0100:                                    "(Ljava/lang/Object;)Lcom/uwyn/rife/continuations/ContinuationContext;");
0101:                    mMethodVisitor.visitVarInsn(ASTORE, mContextIndex);
0102:                    debugMessage("CONT: context set up");
0103:
0104:                    if (pauseCount > 0) {
0105:                        debugMessage("CONT: context obtain label");
0106:                        // get a reference to the context object
0107:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0108:                        // retrieve the current label index
0109:                        mMethodVisitor
0110:                                .visitMethodInsn(
0111:                                        INVOKEVIRTUAL,
0112:                                        "com/uwyn/rife/continuations/ContinuationContext",
0113:                                        "getLabel", "()I");
0114:                        debugMessage("CONT: evaluate tableswitch");
0115:                        mMethodVisitor.visitTableSwitchInsn(0, pauseCount - 1,
0116:                                mDefaultLabel, mLabels);
0117:
0118:                        // set the default label to the start of the code
0119:                        mMethodVisitor.visitLabel(mDefaultLabel);
0120:                        debugMessage("CONT: begin of code");
0121:                    }
0122:                }
0123:            }
0124:
0125:            // store an integer on the stack
0126:            private void addIntegerConst(int value) {
0127:                switch (value) {
0128:                case 0:
0129:                    mMethodVisitor.visitInsn(ICONST_0);
0130:                    break;
0131:                case 1:
0132:                    mMethodVisitor.visitInsn(ICONST_1);
0133:                    break;
0134:                case 2:
0135:                    mMethodVisitor.visitInsn(ICONST_2);
0136:                    break;
0137:                case 3:
0138:                    mMethodVisitor.visitInsn(ICONST_3);
0139:                    break;
0140:                case 4:
0141:                    mMethodVisitor.visitInsn(ICONST_4);
0142:                    break;
0143:                case 5:
0144:                    mMethodVisitor.visitInsn(ICONST_5);
0145:                    break;
0146:                default:
0147:                    mMethodVisitor.visitLdcInsn(value);
0148:                    break;
0149:                }
0150:            }
0151:
0152:            /**
0153:             * Visits a local variable instruction. A local variable instruction is an
0154:             * instruction that loads or stores the value of a local variable.
0155:             *
0156:             * @param opcode the opcode of the local variable instruction to be visited.
0157:             *      This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
0158:             *      LSTORE, FSTORE, DSTORE, ASTORE or RET.
0159:             * @param var the operand of the instruction to be visited. This operand is
0160:             *      the index of a local variable.
0161:             */
0162:            public void visitVarInsn(int opcode, int var) {
0163:                ///CLOVER:OFF
0164:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0165:                    ContinuationDebug.LOGGER
0166:                            .finest(" Code:visitVarInsn            ("
0167:                                    + OPCODES[opcode] + ", " + var + ")");
0168:                ///CLOVER:ON
0169:
0170:                if (mAdapt) {
0171:                    // execute the original opcode
0172:                    mMethodVisitor.visitVarInsn(opcode, var);
0173:
0174:                    // if this is an exception block, check if the caught exception is a
0175:                    // pause exception, if it is, just throw it further again.
0176:                    if (mLabelContext != null
0177:                            && TypesNode.EXCEPTION == mLabelContext.getSort()
0178:                            && ASTORE == opcode) {
0179:                        Label label = new Label();
0180:                        mMethodVisitor.visitVarInsn(ALOAD, var);
0181:                        mMethodVisitor
0182:                                .visitTypeInsn(INSTANCEOF,
0183:                                        "com/uwyn/rife/continuations/exceptions/PauseException");
0184:                        mMethodVisitor.visitJumpInsn(IFEQ, label);
0185:                        mMethodVisitor.visitVarInsn(ALOAD, var);
0186:                        mMethodVisitor.visitJumpInsn(GOTO, mRethrowLabel);
0187:                        mMethodVisitor.visitLabel(label);
0188:                        mUseRethrowLabel = true;
0189:                    }
0190:
0191:                    // catch local variable store opcodes so that they can also be
0192:                    // stored in the context object
0193:                    if (opcode == ISTORE || opcode == LSTORE
0194:                            || opcode == FSTORE || opcode == DSTORE
0195:                            || opcode == ASTORE) {
0196:                        // retain the maximum index of the local var storage
0197:                        if (var > mMaxLocalIndex) {
0198:                            mMaxLocalIndex = var;
0199:                        }
0200:
0201:                        // prepare the arguments of the context storage method
0202:
0203:                        // get a reference to the context object
0204:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0205:                        // get a reference to the local variable stack
0206:                        mMethodVisitor
0207:                                .visitMethodInsn(
0208:                                        INVOKEVIRTUAL,
0209:                                        "com/uwyn/rife/continuations/ContinuationContext",
0210:                                        "getLocalVars",
0211:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0212:
0213:                        // push the index of local var that has to be stored on the
0214:                        // stack
0215:                        addIntegerConst(var);
0216:
0217:                        // detect the opcode and handle the different local variable
0218:                        // types correctly
0219:                        switch (opcode) {
0220:                        // store ints
0221:                        case ISTORE:
0222:                            mMethodVisitor.visitVarInsn(ILOAD, var);
0223:                            mMethodVisitor
0224:                                    .visitMethodInsn(
0225:                                            INVOKEVIRTUAL,
0226:                                            "com/uwyn/rife/continuations/ContinuationStack",
0227:                                            "storeInt", "(II)V");
0228:                            break;
0229:                        // store longs
0230:                        case LSTORE:
0231:                            mMethodVisitor.visitVarInsn(LLOAD, var);
0232:                            mMethodVisitor
0233:                                    .visitMethodInsn(
0234:                                            INVOKEVIRTUAL,
0235:                                            "com/uwyn/rife/continuations/ContinuationStack",
0236:                                            "storeLong", "(IJ)V");
0237:                            break;
0238:                        // store floats
0239:                        case FSTORE:
0240:                            mMethodVisitor.visitVarInsn(FLOAD, var);
0241:                            mMethodVisitor
0242:                                    .visitMethodInsn(
0243:                                            INVOKEVIRTUAL,
0244:                                            "com/uwyn/rife/continuations/ContinuationStack",
0245:                                            "storeFloat", "(IF)V");
0246:                            break;
0247:                        // store doubles
0248:                        case DSTORE:
0249:                            mMethodVisitor.visitVarInsn(DLOAD, var);
0250:                            mMethodVisitor
0251:                                    .visitMethodInsn(
0252:                                            INVOKEVIRTUAL,
0253:                                            "com/uwyn/rife/continuations/ContinuationStack",
0254:                                            "storeDouble", "(ID)V");
0255:                            break;
0256:                        // store references
0257:                        case ASTORE:
0258:                            mMethodVisitor.visitVarInsn(ALOAD, var);
0259:                            mMethodVisitor
0260:                                    .visitMethodInsn(
0261:                                            INVOKEVIRTUAL,
0262:                                            "com/uwyn/rife/continuations/ContinuationStack",
0263:                                            "storeReference",
0264:                                            "(ILjava/lang/Object;)V");
0265:                            break;
0266:                        }
0267:                    }
0268:
0269:                    // if this was the first ASTORE of an exception block, restore
0270:                    // the local types and change the type of the block so that this
0271:                    // isn't executed anymore
0272:                    if (mLabelContext != null
0273:                            && TypesNode.EXCEPTION == mLabelContext.getSort()
0274:                            && ASTORE == opcode) {
0275:                        // restore the local variable stack
0276:                        restoreLocalStack(mLabelContext);
0277:
0278:                        mLabelContext.setSort(TypesNode.REGULAR);
0279:                    }
0280:                } else if (mVisit) {
0281:                    mMethodVisitor.visitVarInsn(opcode, var);
0282:                }
0283:            }
0284:
0285:            /**
0286:             * Visits a method instruction. A method instruction is an instruction that
0287:             * invokes a method.
0288:             *
0289:             * @param opcode the opcode of the type instruction to be visited. This opcode
0290:             *      is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
0291:             *      INVOKEINTERFACE.
0292:             * @param owner the internal name of the method's owner class (see {@link
0293:             *      Type#getInternalName getInternalName}).
0294:             * @param name the method's name.
0295:             * @param desc the method's descriptor (see {@link Type Type}).
0296:             */
0297:            public void visitMethodInsn(int opcode, String owner, String name,
0298:                    String desc) {
0299:                ///CLOVER:OFF
0300:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0301:                    ContinuationDebug.LOGGER
0302:                            .finest(" Code:visitMethodInsn         ("
0303:                                    + OPCODES[opcode] + ", \"" + owner
0304:                                    + "\", \"" + name + "\", \"" + desc + "\")");
0305:                ///CLOVER:ON
0306:
0307:                if (mAdapt) {
0308:                    String owner_classname = owner.replace('/', '.');
0309:
0310:                    if (owner_classname.equals(mConfig
0311:                            .getContinuableSupportClassName())
0312:                            || mClassName.equals(owner_classname)) {
0313:                        if (mConfig.getPauseMethodName().equals(name)
0314:                                && "()V".equals(desc)) {
0315:                            debugMessage("CONT: pause : undoing method call");
0316:
0317:                            // pop the ALOAD opcode off the stack
0318:                            mMethodVisitor.visitInsn(POP);
0319:
0320:                            TypesContext context = mTypes.nextPauseContext();
0321:                            Stack<String> stack = context.getStackClone();
0322:                            debugMessage("CONT: pause : saving operand stack");
0323:                            saveOperandStack(stack);
0324:
0325:                            debugMessage("CONT: pause : storing resume label");
0326:                            // get a reference to the context object
0327:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0328:                            // set the index of the current label
0329:                            addIntegerConst(mLabelIndex);
0330:                            // set the new label index
0331:                            mMethodVisitor
0332:                                    .visitMethodInsn(
0333:                                            INVOKEVIRTUAL,
0334:                                            "com/uwyn/rife/continuations/ContinuationContext",
0335:                                            "setLabel", "(I)V");
0336:
0337:                            // generate the pause exception
0338:                            debugMessage("CONT: pause : throwing pause exception");
0339:                            mMethodVisitor
0340:                                    .visitTypeInsn(NEW,
0341:                                            "com/uwyn/rife/continuations/exceptions/PauseException");
0342:                            mMethodVisitor.visitInsn(DUP);
0343:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0344:                            mMethodVisitor
0345:                                    .visitMethodInsn(
0346:                                            INVOKESPECIAL,
0347:                                            "com/uwyn/rife/continuations/exceptions/PauseException",
0348:                                            "<init>",
0349:                                            "(Lcom/uwyn/rife/continuations/ContinuationContext;)V");
0350:                            mMethodVisitor.visitInsn(ATHROW);
0351:
0352:                            // add label for skipping over resumed code
0353:                            mMethodVisitor.visitLabel(mLabels[mLabelIndex]);
0354:                            debugMessage("CONT: pause : resumed execution");
0355:
0356:                            // restore the local variable stack
0357:                            debugMessage("CONT: pause : restoring local stack");
0358:                            restoreLocalStack(context);
0359:
0360:                            // restore the local operand stack
0361:                            debugMessage("CONT: pause : restoring operand stack");
0362:                            restoreOperandStack(stack);
0363:
0364:                            mLabelIndex++;
0365:
0366:                            return;
0367:                        } else if (mConfig.getStepbackMethodName().equals(name)
0368:                                && "()V".equals(desc)) {
0369:                            debugMessage("CONT: stepBack : undoing method call");
0370:
0371:                            // pop the ALOAD opcode off the stack
0372:                            mMethodVisitor.visitInsn(POP);
0373:
0374:                            TypesContext context = mTypes.nextPauseContext();
0375:                            Stack<String> stack = context.getStackClone();
0376:                            debugMessage("CONT: stepBack : saving operand stack");
0377:                            saveOperandStack(stack);
0378:
0379:                            // generate the stepBack exception
0380:                            debugMessage("CONT: stepBack : throwing pause exception");
0381:                            mMethodVisitor
0382:                                    .visitTypeInsn(NEW,
0383:                                            "com/uwyn/rife/continuations/exceptions/StepBackException");
0384:                            mMethodVisitor.visitInsn(DUP);
0385:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0386:                            mMethodVisitor
0387:                                    .visitMethodInsn(
0388:                                            INVOKESPECIAL,
0389:                                            "com/uwyn/rife/continuations/exceptions/StepBackException",
0390:                                            "<init>",
0391:                                            "(Lcom/uwyn/rife/continuations/ContinuationContext;)V");
0392:                            mMethodVisitor.visitInsn(ATHROW);
0393:
0394:                            // add label for skipping over resumed code
0395:                            mMethodVisitor.visitLabel(mLabels[mLabelIndex]);
0396:                            debugMessage("CONT: stepBack : resumed execution");
0397:
0398:                            // restore the local variable stack
0399:                            debugMessage("CONT: stepBack : restoring local stack");
0400:                            restoreLocalStack(context);
0401:
0402:                            // restore the local operand stack
0403:                            debugMessage("CONT: stepBack : restoring operand stack");
0404:                            restoreOperandStack(stack);
0405:
0406:                            mLabelIndex++;
0407:
0408:                            return;
0409:                        } else if (mConfig.getCallMethodName().equals(name)
0410:                                && Type.getMethodDescriptor(
0411:                                        mConfig.getCallMethodReturnType(),
0412:                                        mConfig.getCallMethodArgumentTypes())
0413:                                        .equals(desc)) {
0414:                            // store the call target
0415:                            debugMessage("CONT: call : storing call target");
0416:                            mMethodVisitor.visitVarInsn(ASTORE,
0417:                                    mCallTargetIndex);
0418:
0419:                            // pop the ALOAD opcode off the stack
0420:                            debugMessage("CONT: call : undoing method call");
0421:                            mMethodVisitor.visitInsn(POP);
0422:
0423:                            TypesContext context = mTypes.nextPauseContext();
0424:                            Stack<String> stack = context.getStackClone();
0425:                            stack.pop();
0426:                            debugMessage("CONT: call : saving operand stack");
0427:                            saveOperandStack(stack);
0428:
0429:                            debugMessage("CONT: call : storing resume label");
0430:                            // get a reference to the context object
0431:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0432:                            // set the index of the current label
0433:                            addIntegerConst(mLabelIndex);
0434:                            // set the new label index
0435:                            mMethodVisitor
0436:                                    .visitMethodInsn(
0437:                                            INVOKEVIRTUAL,
0438:                                            "com/uwyn/rife/continuations/ContinuationContext",
0439:                                            "setLabel", "(I)V");
0440:
0441:                            // generate the pause exception
0442:                            debugMessage("CONT: call : throwing call exception");
0443:                            mMethodVisitor
0444:                                    .visitTypeInsn(NEW,
0445:                                            "com/uwyn/rife/continuations/exceptions/CallException");
0446:                            mMethodVisitor.visitInsn(DUP);
0447:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0448:                            mMethodVisitor
0449:                                    .visitVarInsn(ALOAD, mCallTargetIndex);
0450:                            mMethodVisitor
0451:                                    .visitMethodInsn(
0452:                                            INVOKESPECIAL,
0453:                                            "com/uwyn/rife/continuations/exceptions/CallException",
0454:                                            "<init>",
0455:                                            "(Lcom/uwyn/rife/continuations/ContinuationContext;Ljava/lang/Object;)V");
0456:                            mMethodVisitor.visitInsn(ATHROW);
0457:
0458:                            // add label for skipping over resumed code
0459:                            mMethodVisitor.visitLabel(mLabels[mLabelIndex]);
0460:                            debugMessage("CONT: call : resumed execution");
0461:
0462:                            // restore the local variable stack
0463:                            debugMessage("CONT: call : restoring local stack");
0464:                            restoreLocalStack(context);
0465:                            // restore the local operand stack
0466:                            debugMessage("CONT: call : restoring operand stack");
0467:                            restoreOperandStack(stack);
0468:
0469:                            debugMessage("CONT: call : retrieving call answer");
0470:                            // get a reference to the context object
0471:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0472:                            // get the call answer
0473:                            mMethodVisitor
0474:                                    .visitMethodInsn(
0475:                                            INVOKEVIRTUAL,
0476:                                            "com/uwyn/rife/continuations/ContinuationContext",
0477:                                            "getCallAnswer",
0478:                                            "()Ljava/lang/Object;");
0479:                            mMethodVisitor.visitTypeInsn(CHECKCAST, Type
0480:                                    .getInternalName(mConfig
0481:                                            .getCallMethodReturnType()));
0482:
0483:                            mLabelIndex++;
0484:
0485:                            return;
0486:                        } else if (mConfig.getAnswerMethodName().equals(name)
0487:                                && ("()V".equals(desc) || "(Ljava/lang/Object;)V"
0488:                                        .equals(desc))) {
0489:                            if ("()V".equals(desc)) {
0490:                                mMethodVisitor.visitInsn(ACONST_NULL);
0491:                            }
0492:
0493:                            // store the answer
0494:                            debugMessage("CONT: call : storing answer");
0495:                            mMethodVisitor.visitVarInsn(ASTORE, mAnswerIndex);
0496:
0497:                            // pop the ALOAD opcode off the stack
0498:                            debugMessage("CONT: call : undoing method call");
0499:                            mMethodVisitor.visitInsn(POP);
0500:
0501:                            // generate the answer exception
0502:                            debugMessage("CONT: answer : throwing answer exception");
0503:                            mMethodVisitor
0504:                                    .visitTypeInsn(NEW,
0505:                                            "com/uwyn/rife/continuations/exceptions/AnswerException");
0506:                            mMethodVisitor.visitInsn(DUP);
0507:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0508:                            mMethodVisitor.visitVarInsn(ALOAD, mAnswerIndex);
0509:                            mMethodVisitor
0510:                                    .visitMethodInsn(
0511:                                            INVOKESPECIAL,
0512:                                            "com/uwyn/rife/continuations/exceptions/AnswerException",
0513:                                            "<init>",
0514:                                            "(Lcom/uwyn/rife/continuations/ContinuationContext;Ljava/lang/Object;)V");
0515:                            mMethodVisitor.visitInsn(ATHROW);
0516:
0517:                            return;
0518:                        }
0519:                    }
0520:                }
0521:
0522:                if (mVisit) {
0523:                    mMethodVisitor.visitMethodInsn(opcode, owner, name, desc);
0524:                }
0525:            }
0526:
0527:            /**
0528:             * Restore the local variable stack, first the computation
0529:             * types of category 1 and afterwards those of category 2
0530:             */
0531:            private void restoreLocalStack(TypesContext context) {
0532:                for (int i = 1; i <= mMaxLocalIndex; i++) {
0533:                    if (!context.hasVar(i)) {
0534:                        continue;
0535:                    }
0536:
0537:                    switch (context.getVarType(i)) {
0538:                    case Type.INT:
0539:                        debugMessage("CONT: restore local : " + i + ", int");
0540:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0541:                        mMethodVisitor
0542:                                .visitMethodInsn(
0543:                                        INVOKEVIRTUAL,
0544:                                        "com/uwyn/rife/continuations/ContinuationContext",
0545:                                        "getLocalVars",
0546:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0547:                        addIntegerConst(i);
0548:                        mMethodVisitor
0549:                                .visitMethodInsn(
0550:                                        INVOKEVIRTUAL,
0551:                                        "com/uwyn/rife/continuations/ContinuationStack",
0552:                                        "getInt", "(I)I");
0553:                        mMethodVisitor.visitVarInsn(ISTORE, i);
0554:                        break;
0555:                    case Type.FLOAT:
0556:                        debugMessage("CONT: restore local : " + i + ", float");
0557:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0558:                        mMethodVisitor
0559:                                .visitMethodInsn(
0560:                                        INVOKEVIRTUAL,
0561:                                        "com/uwyn/rife/continuations/ContinuationContext",
0562:                                        "getLocalVars",
0563:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0564:                        addIntegerConst(i);
0565:                        mMethodVisitor
0566:                                .visitMethodInsn(
0567:                                        INVOKEVIRTUAL,
0568:                                        "com/uwyn/rife/continuations/ContinuationStack",
0569:                                        "getFloat", "(I)F");
0570:                        mMethodVisitor.visitVarInsn(FSTORE, i);
0571:                        break;
0572:                    case Type.OBJECT:
0573:                        debugMessage("CONT: restore local : " + i + ", "
0574:                                + context.getVar(i) + "");
0575:                        String type = context.getVar(i);
0576:                        if (NULL.equals(type)) {
0577:                            mMethodVisitor.visitInsn(ACONST_NULL);
0578:                            mMethodVisitor.visitVarInsn(ASTORE, i);
0579:                        } else {
0580:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0581:                            mMethodVisitor
0582:                                    .visitMethodInsn(
0583:                                            INVOKEVIRTUAL,
0584:                                            "com/uwyn/rife/continuations/ContinuationContext",
0585:                                            "getLocalVars",
0586:                                            "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0587:                            addIntegerConst(i);
0588:                            mMethodVisitor
0589:                                    .visitMethodInsn(
0590:                                            INVOKEVIRTUAL,
0591:                                            "com/uwyn/rife/continuations/ContinuationStack",
0592:                                            "getReference",
0593:                                            "(I)Ljava/lang/Object;");
0594:                            mMethodVisitor.visitTypeInsn(CHECKCAST, type);
0595:                            mMethodVisitor.visitVarInsn(ASTORE, i);
0596:                        }
0597:
0598:                        break;
0599:                    }
0600:                }
0601:                for (int i = 1; i <= mMaxLocalIndex; i++) {
0602:                    if (!context.hasVar(i)) {
0603:                        continue;
0604:                    }
0605:
0606:                    switch (context.getVarType(i)) {
0607:                    case Type.LONG:
0608:                        debugMessage("CONT: restore local : " + i + ", long");
0609:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0610:                        mMethodVisitor
0611:                                .visitMethodInsn(
0612:                                        INVOKEVIRTUAL,
0613:                                        "com/uwyn/rife/continuations/ContinuationContext",
0614:                                        "getLocalVars",
0615:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0616:                        addIntegerConst(i);
0617:                        mMethodVisitor
0618:                                .visitMethodInsn(
0619:                                        INVOKEVIRTUAL,
0620:                                        "com/uwyn/rife/continuations/ContinuationStack",
0621:                                        "getLong", "(I)J");
0622:                        mMethodVisitor.visitVarInsn(LSTORE, i);
0623:                        break;
0624:                    case Type.DOUBLE:
0625:                        debugMessage("CONT: restore local : " + i + ", double");
0626:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0627:                        mMethodVisitor
0628:                                .visitMethodInsn(
0629:                                        INVOKEVIRTUAL,
0630:                                        "com/uwyn/rife/continuations/ContinuationContext",
0631:                                        "getLocalVars",
0632:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0633:                        addIntegerConst(i);
0634:                        mMethodVisitor
0635:                                .visitMethodInsn(
0636:                                        INVOKEVIRTUAL,
0637:                                        "com/uwyn/rife/continuations/ContinuationStack",
0638:                                        "getDouble", "(I)D");
0639:                        mMethodVisitor.visitVarInsn(DSTORE, i);
0640:                        break;
0641:                    }
0642:                }
0643:            }
0644:
0645:            /**
0646:             * Save the operand stack
0647:             */
0648:            private void saveOperandStack(Stack<String> stack) {
0649:                String tupe = null;
0650:
0651:                // save all stack entries besides the last one pushed, it's the
0652:                // element's object reference that is used for the stub continuation
0653:                // methods
0654:                for (int i = stack.size() - 1; i >= 0; i--) {
0655:                    tupe = stack.get(i);
0656:
0657:                    if (tupe.equals(CAT1_BOOLEAN) || tupe.equals(CAT1_CHAR)
0658:                            || tupe.equals(CAT1_BYTE)
0659:                            || tupe.equals(CAT1_SHORT) || tupe.equals(CAT1_INT)) {
0660:                        mMethodVisitor.visitVarInsn(ISTORE, mTempIndex);
0661:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0662:                        mMethodVisitor
0663:                                .visitMethodInsn(
0664:                                        INVOKEVIRTUAL,
0665:                                        "com/uwyn/rife/continuations/ContinuationContext",
0666:                                        "getLocalStack",
0667:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0668:                        mMethodVisitor.visitVarInsn(ILOAD, mTempIndex);
0669:                        mMethodVisitor
0670:                                .visitMethodInsn(
0671:                                        INVOKEVIRTUAL,
0672:                                        "com/uwyn/rife/continuations/ContinuationStack",
0673:                                        "pushInt", "(I)V");
0674:                    } else if (tupe.equals(CAT1_FLOAT)) {
0675:                        mMethodVisitor.visitVarInsn(FSTORE, mTempIndex);
0676:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0677:                        mMethodVisitor
0678:                                .visitMethodInsn(
0679:                                        INVOKEVIRTUAL,
0680:                                        "com/uwyn/rife/continuations/ContinuationContext",
0681:                                        "getLocalStack",
0682:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0683:                        mMethodVisitor.visitVarInsn(FLOAD, mTempIndex);
0684:                        mMethodVisitor
0685:                                .visitMethodInsn(
0686:                                        INVOKEVIRTUAL,
0687:                                        "com/uwyn/rife/continuations/ContinuationStack",
0688:                                        "pushFloat", "(F)V");
0689:                    } else if (tupe.equals(CAT2_DOUBLE)) {
0690:                        mMethodVisitor.visitVarInsn(DSTORE, mTempIndex);
0691:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0692:                        mMethodVisitor
0693:                                .visitMethodInsn(
0694:                                        INVOKEVIRTUAL,
0695:                                        "com/uwyn/rife/continuations/ContinuationContext",
0696:                                        "getLocalStack",
0697:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0698:                        mMethodVisitor.visitVarInsn(DLOAD, mTempIndex);
0699:                        mMethodVisitor
0700:                                .visitMethodInsn(
0701:                                        INVOKEVIRTUAL,
0702:                                        "com/uwyn/rife/continuations/ContinuationStack",
0703:                                        "pushDouble", "(D)V");
0704:                    } else if (tupe.equals(CAT2_LONG)) {
0705:                        mMethodVisitor.visitVarInsn(LSTORE, mTempIndex);
0706:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0707:                        mMethodVisitor
0708:                                .visitMethodInsn(
0709:                                        INVOKEVIRTUAL,
0710:                                        "com/uwyn/rife/continuations/ContinuationContext",
0711:                                        "getLocalStack",
0712:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0713:                        mMethodVisitor.visitVarInsn(LLOAD, mTempIndex);
0714:                        mMethodVisitor
0715:                                .visitMethodInsn(
0716:                                        INVOKEVIRTUAL,
0717:                                        "com/uwyn/rife/continuations/ContinuationStack",
0718:                                        "pushLong", "(J)V");
0719:                    } else if (tupe.equals(CAT1_ADDRESS)) {
0720:                        // this should never happen
0721:                        throw new RuntimeException("Invalid local stack type");
0722:                    } else {
0723:                        mMethodVisitor.visitVarInsn(ASTORE, mTempIndex);
0724:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0725:                        mMethodVisitor
0726:                                .visitMethodInsn(
0727:                                        INVOKEVIRTUAL,
0728:                                        "com/uwyn/rife/continuations/ContinuationContext",
0729:                                        "getLocalStack",
0730:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0731:                        mMethodVisitor.visitVarInsn(ALOAD, mTempIndex);
0732:                        mMethodVisitor
0733:                                .visitMethodInsn(
0734:                                        INVOKEVIRTUAL,
0735:                                        "com/uwyn/rife/continuations/ContinuationStack",
0736:                                        "pushReference",
0737:                                        "(Ljava/lang/Object;)V");
0738:                    }
0739:                }
0740:            }
0741:
0742:            /**
0743:             * Restore the operand stack
0744:             */
0745:            private void restoreOperandStack(Stack<String> stack) {
0746:                String type = null;
0747:
0748:                // restore all stack entries besides the last one pushed, it's the
0749:                // element's object reference that is used for the stub continuation
0750:                // methods
0751:                for (int i = 0; i < stack.size(); i++) {
0752:                    type = stack.get(i);
0753:
0754:                    if (type.equals(CAT1_BOOLEAN) || type.equals(CAT1_CHAR)
0755:                            || type.equals(CAT1_BYTE)
0756:                            || type.equals(CAT1_SHORT) || type.equals(CAT1_INT)) {
0757:                        debugMessage("CONT: restore operand : " + i + ", int");
0758:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0759:                        mMethodVisitor
0760:                                .visitMethodInsn(
0761:                                        INVOKEVIRTUAL,
0762:                                        "com/uwyn/rife/continuations/ContinuationContext",
0763:                                        "getLocalStack",
0764:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0765:                        mMethodVisitor
0766:                                .visitMethodInsn(
0767:                                        INVOKEVIRTUAL,
0768:                                        "com/uwyn/rife/continuations/ContinuationStack",
0769:                                        "popInt", "()I");
0770:                    } else if (type.equals(CAT1_FLOAT)) {
0771:                        debugMessage("CONT: restore operand : " + i + ", float");
0772:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0773:                        mMethodVisitor
0774:                                .visitMethodInsn(
0775:                                        INVOKEVIRTUAL,
0776:                                        "com/uwyn/rife/continuations/ContinuationContext",
0777:                                        "getLocalStack",
0778:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0779:                        mMethodVisitor
0780:                                .visitMethodInsn(
0781:                                        INVOKEVIRTUAL,
0782:                                        "com/uwyn/rife/continuations/ContinuationStack",
0783:                                        "popFloat", "()F");
0784:                    } else if (type.equals(CAT2_DOUBLE)) {
0785:                        debugMessage("CONT: restore operand : " + i
0786:                                + ", double");
0787:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0788:                        mMethodVisitor
0789:                                .visitMethodInsn(
0790:                                        INVOKEVIRTUAL,
0791:                                        "com/uwyn/rife/continuations/ContinuationContext",
0792:                                        "getLocalStack",
0793:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0794:                        mMethodVisitor
0795:                                .visitMethodInsn(
0796:                                        INVOKEVIRTUAL,
0797:                                        "com/uwyn/rife/continuations/ContinuationStack",
0798:                                        "popDouble", "()D");
0799:                    } else if (type.equals(CAT2_LONG)) {
0800:                        debugMessage("CONT: restore operand : " + i + ", long");
0801:                        mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0802:                        mMethodVisitor
0803:                                .visitMethodInsn(
0804:                                        INVOKEVIRTUAL,
0805:                                        "com/uwyn/rife/continuations/ContinuationContext",
0806:                                        "getLocalStack",
0807:                                        "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0808:                        mMethodVisitor
0809:                                .visitMethodInsn(
0810:                                        INVOKEVIRTUAL,
0811:                                        "com/uwyn/rife/continuations/ContinuationStack",
0812:                                        "popLong", "()J");
0813:                    } else if (type.equals(CAT1_ADDRESS)) {
0814:                        // this should never happen
0815:                        throw new RuntimeException("Invalid local stack type");
0816:                    } else {
0817:                        debugMessage("CONT: restore operand : " + i + ", "
0818:                                + type);
0819:                        if (NULL.equals(type)) {
0820:                            mMethodVisitor.visitInsn(ACONST_NULL);
0821:                            mMethodVisitor.visitVarInsn(ASTORE, i);
0822:                        } else {
0823:                            mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0824:                            mMethodVisitor
0825:                                    .visitMethodInsn(
0826:                                            INVOKEVIRTUAL,
0827:                                            "com/uwyn/rife/continuations/ContinuationContext",
0828:                                            "getLocalStack",
0829:                                            "()Lcom/uwyn/rife/continuations/ContinuationStack;");
0830:                            mMethodVisitor
0831:                                    .visitMethodInsn(
0832:                                            INVOKEVIRTUAL,
0833:                                            "com/uwyn/rife/continuations/ContinuationStack",
0834:                                            "popReference",
0835:                                            "()Ljava/lang/Object;");
0836:                            mMethodVisitor.visitTypeInsn(CHECKCAST, type);
0837:                        }
0838:                    }
0839:                }
0840:            }
0841:
0842:            /**
0843:             * Visits a type instruction. A type instruction is an instruction that
0844:             * takes a type descriptor as parameter.
0845:             *
0846:             * @param opcode the opcode of the type instruction to be visited. This opcode
0847:             *      is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
0848:             * @param desc the operand of the instruction to be visited. This operand is
0849:             *      must be a fully qualified class name in internal form, or the type
0850:             *      descriptor of an array type (see {@link Type Type}).
0851:             */
0852:            public void visitTypeInsn(int opcode, String desc) {
0853:                ///CLOVER:OFF
0854:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0855:                    ContinuationDebug.LOGGER
0856:                            .finest(" Code:visitTypeInsn           ("
0857:                                    + OPCODES[opcode] + ", \"" + desc + "\")");
0858:                ///CLOVER:ON
0859:
0860:                if (mVisit) {
0861:                    mMethodVisitor.visitTypeInsn(opcode, desc);
0862:                }
0863:            }
0864:
0865:            /**
0866:             * Visits a LDC instruction.
0867:             *
0868:             * @param cst the constant to be loaded on the stack. This parameter must be
0869:             *      a non null {@link java.lang.Integer Integer}, a {@link java.lang.Float
0870:             *      Float}, a {@link java.lang.Long Long}, a {@link java.lang.Double
0871:             *      Double} or a {@link String String}.
0872:             */
0873:            public void visitLdcInsn(Object cst) {
0874:                ///CLOVER:OFF
0875:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0876:                    ContinuationDebug.LOGGER
0877:                            .finest(" Code:visitLdcInsn            (" + cst
0878:                                    + ")");
0879:                ///CLOVER:ON
0880:
0881:                if (mVisit) {
0882:                    mMethodVisitor.visitLdcInsn(cst);
0883:                }
0884:            }
0885:
0886:            /**
0887:             * Visits a MULTIANEWARRAY instruction.
0888:             *
0889:             * @param desc an array type descriptor (see {@link Type Type}).
0890:             * @param dims number of dimensions of the array to allocate.
0891:             */
0892:            public void visitMultiANewArrayInsn(String desc, int dims) {
0893:                ///CLOVER:OFF
0894:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0895:                    ContinuationDebug.LOGGER
0896:                            .finest(" Code:visitMultiANewArrayInsn (\"" + desc
0897:                                    + "\", " + dims + ")");
0898:                ///CLOVER:ON
0899:
0900:                if (mVisit) {
0901:                    mMethodVisitor.visitMultiANewArrayInsn(desc, dims);
0902:                }
0903:            }
0904:
0905:            /**
0906:             * Visits a zero operand instruction.
0907:             *
0908:             * @param opcode the opcode of the instruction to be visited. This opcode is
0909:             *      either NOP, ACONST_NULL, ICONST_1, ICONST_0, ICONST_1, ICONST_2,
0910:             *      ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1,
0911:             *      FCONST_2, DCONST_0, DCONST_1,
0912:             *
0913:             *      IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
0914:             *      IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
0915:             *      SASTORE,
0916:             *
0917:             *      POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP,
0918:             *
0919:             *      IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL,
0920:             *      DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG,
0921:             *      FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR,
0922:             *      LOR, IXOR, LXOR,
0923:             *
0924:             *      I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C,
0925:             *      I2S,
0926:             *
0927:             *      LCMP, FCMPL, FCMPG, DCMPL, DCMPG,
0928:             *
0929:             *      IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN,
0930:             *
0931:             *      ARRAYLENGTH,
0932:             *
0933:             *      ATHROW,
0934:             *
0935:             *      MONITORENTER, or MONITOREXIT.
0936:             */
0937:            public void visitInsn(int opcode) {
0938:                ///CLOVER:OFF
0939:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0940:                    ContinuationDebug.LOGGER
0941:                            .finest(" Code:visitInsn               ("
0942:                                    + OPCODES[opcode] + ")");
0943:                ///CLOVER:ON
0944:
0945:                if (mAdapt && RETURN == opcode) {
0946:                    debugMessage("CONT: context deactivation");
0947:
0948:                    // get a reference to the context object
0949:                    mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0950:                    // remove the context from the manager
0951:                    mMethodVisitor.visitMethodInsn(INVOKEVIRTUAL,
0952:                            "com/uwyn/rife/continuations/ContinuationContext",
0953:                            "registerContext", "()V");
0954:
0955:                    // get a reference to the context object
0956:                    mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
0957:                    // remove the context from the manager
0958:                    mMethodVisitor.visitMethodInsn(INVOKEVIRTUAL,
0959:                            "com/uwyn/rife/continuations/ContinuationContext",
0960:                            "deactivate", "()V");
0961:
0962:                    mMethodVisitor.visitInsn(opcode);
0963:
0964:                    if (mUseRethrowLabel) {
0965:                        mMethodVisitor.visitLabel(mRethrowLabel);
0966:                        debugMessage("CONT: rethrowing exception");
0967:                        mMethodVisitor.visitInsn(ATHROW);
0968:                    }
0969:                } else if (mVisit) {
0970:                    mMethodVisitor.visitInsn(opcode);
0971:                }
0972:            }
0973:
0974:            /**
0975:             * Visits an IINC instruction.
0976:             *
0977:             * @param var index of the local variable to be incremented.
0978:             * @param increment amount to increment the local variable by.
0979:             */
0980:            public void visitIincInsn(int var, int increment) {
0981:                ///CLOVER:OFF
0982:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
0983:                    ContinuationDebug.LOGGER
0984:                            .finest(" Code:visitIincInsn           (" + var
0985:                                    + ", " + increment + ")");
0986:                ///CLOVER:ON
0987:
0988:                if (mAdapt) {
0989:                    // execute the original opcode
0990:                    mMethodVisitor.visitIincInsn(var, increment);
0991:
0992:                    // retain the maximum index of the local var storage
0993:                    if (var > mMaxLocalIndex) {
0994:                        mMaxLocalIndex = var;
0995:                    }
0996:
0997:                    // prepare the arguments of the context storage method
0998:
0999:                    // get a reference to the context object
1000:                    mMethodVisitor.visitVarInsn(ALOAD, mContextIndex);
1001:                    // get a reference to the local variable stack
1002:                    mMethodVisitor
1003:                            .visitMethodInsn(
1004:                                    INVOKEVIRTUAL,
1005:                                    "com/uwyn/rife/continuations/ContinuationContext",
1006:                                    "getLocalVars",
1007:                                    "()Lcom/uwyn/rife/continuations/ContinuationStack;");
1008:
1009:                    // push the index of local var that has to be stored on the
1010:                    // stack and put the increment amount on it also
1011:                    addIntegerConst(var);
1012:                    addIntegerConst(increment);
1013:                    mMethodVisitor.visitMethodInsn(INVOKEVIRTUAL,
1014:                            "com/uwyn/rife/continuations/ContinuationStack",
1015:                            "incrementInt", "(II)V");
1016:                } else if (mVisit) {
1017:                    mMethodVisitor.visitIincInsn(var, increment);
1018:                }
1019:            }
1020:
1021:            /**
1022:             * Visits a field instruction. A field instruction is an instruction that
1023:             * loads or stores the value of a field of an object.
1024:             *
1025:             * @param opcode the opcode of the type instruction to be visited. This opcode
1026:             *      is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
1027:             * @param owner the internal name of the field's owner class (see {@link
1028:             *      Type#getInternalName getInternalName}).
1029:             * @param name the field's name.
1030:             * @param desc the field's descriptor (see {@link Type Type}).
1031:             */
1032:            public void visitFieldInsn(int opcode, String owner, String name,
1033:                    String desc) {
1034:                ///CLOVER:OFF
1035:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1036:                    ContinuationDebug.LOGGER
1037:                            .finest(" Code:visitFieldInsn          ("
1038:                                    + OPCODES[opcode] + ", \"" + owner
1039:                                    + "\", \"" + name + "\", \"" + desc + "\")");
1040:                ///CLOVER:ON
1041:
1042:                if (mAdapt && !mDisabledCodeguideBackInTime
1043:                        && opcode == GETSTATIC
1044:                        && mClassNameInternal.equals(owner)
1045:                        && name.startsWith("debugEnabled$") && "Z".equals(desc)) {
1046:                    mDisableCodeguideBackInTime = true;
1047:                }
1048:
1049:                if (mVisit) {
1050:                    mMethodVisitor.visitFieldInsn(opcode, owner, name, desc);
1051:                }
1052:            }
1053:
1054:            /**
1055:             * Visits an instruction with a single int operand.
1056:             *
1057:             * @param opcode the opcode of the instruction to be visited. This opcode is
1058:             *      either BIPUSH, SIPUSH or NEWARRAY.
1059:             * @param operand the operand of the instruction to be visited.
1060:             */
1061:            public void visitIntInsn(int opcode, int operand) {
1062:                ///CLOVER:OFF
1063:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1064:                    ContinuationDebug.LOGGER
1065:                            .finest(" Code:visitIntInsn            ("
1066:                                    + OPCODES[opcode] + ", " + operand + ")");
1067:                ///CLOVER:ON
1068:
1069:                if (mVisit) {
1070:                    mMethodVisitor.visitIntInsn(opcode, operand);
1071:                }
1072:            }
1073:
1074:            /**
1075:             * Visits a try catch block.
1076:             *
1077:             * @param start beginning of the exception handler's scope (inclusive).
1078:             * @param end end of the exception handler's scope (exclusive).
1079:             * @param handler beginning of the exception handler's code.
1080:             * @param type internal name of the type of exceptions handled by the handler,
1081:             *      or <tt>null</tt> to catch any exceptions (for "finally" blocks).
1082:             * @throws IllegalArgumentException if one of the labels has not already been
1083:             *      visited by this visitor (by the {@link #visitLabel visitLabel}
1084:             *      method).
1085:             */
1086:            public void visitTryCatchBlock(Label start, Label end,
1087:                    Label handler, String type) {
1088:                ///CLOVER:OFF
1089:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1090:                    ContinuationDebug.LOGGER
1091:                            .finest(" Code:visitTryCatchBlock      (" + start
1092:                                    + ", " + end + ", " + handler + ", \""
1093:                                    + type + "\")");
1094:                ///CLOVER:ON
1095:
1096:                if (mVisit) {
1097:                    mMethodVisitor
1098:                            .visitTryCatchBlock(start, end, handler, type);
1099:                }
1100:            }
1101:
1102:            /**
1103:             * Visits a LOOKUPSWITCH instruction.
1104:             *
1105:             * @param dflt beginning of the default handler block.
1106:             * @param keys the values of the keys.
1107:             * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
1108:             *      beginning of the handler block for the <tt>keys[i]</tt> key.
1109:             */
1110:            public void visitLookupSwitchInsn(Label dflt, int[] keys,
1111:                    Label[] labels) {
1112:                ///CLOVER:OFF
1113:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1114:                    ContinuationDebug.LOGGER
1115:                            .finest(" Code:visitLookupSwitchInsn   ("
1116:                                    + dflt
1117:                                    + ", "
1118:                                    + (null == keys ? null : join(keys, ","))
1119:                                    + ", "
1120:                                    + (null == labels ? null
1121:                                            : join(labels, ",")) + ")");
1122:                ///CLOVER:ON
1123:
1124:                if (mVisit) {
1125:                    mMethodVisitor.visitLookupSwitchInsn(dflt, keys, labels);
1126:                }
1127:            }
1128:
1129:            /**
1130:             * Visits a jump instruction. A jump instruction is an instruction that may
1131:             * jump to another instruction.
1132:             *
1133:             * @param opcode the opcode of the type instruction to be visited. This opcode
1134:             *      is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE,
1135:             *      IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE,
1136:             *      GOTO, JSR, IFNULL or IFNONNULL.
1137:             * @param label the operand of the instruction to be visited. This operand is
1138:             *      a label that designates the instruction to which the jump instruction
1139:             *      may jump.
1140:             */
1141:            public void visitJumpInsn(int opcode, Label label) {
1142:                ///CLOVER:OFF
1143:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1144:                    ContinuationDebug.LOGGER
1145:                            .finest(" Code:visitJumpInsn           ("
1146:                                    + OPCODES[opcode] + ", " + label + ")");
1147:                ///CLOVER:ON
1148:
1149:                if (mAdapt && mDisableCodeguideBackInTime && opcode == IFEQ) {
1150:                    // pop the condition value off the stack
1151:                    mMethodVisitor.visitInsn(POP);
1152:                    mMethodVisitor.visitJumpInsn(GOTO, label);
1153:                    mDisableCodeguideBackInTime = false;
1154:                    mDisabledCodeguideBackInTime = true;
1155:                } else if (mVisit) {
1156:                    mMethodVisitor.visitJumpInsn(opcode, label);
1157:                }
1158:            }
1159:
1160:            /**
1161:             * Visits a label. A label designates the instruction that will be visited
1162:             * just after it.
1163:             *
1164:             * @param label a {@link Label Label} object.
1165:             */
1166:            public void visitLabel(Label label) {
1167:                ///CLOVER:OFF
1168:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1169:                    ContinuationDebug.LOGGER
1170:                            .finest(" Code:visitLabel              (" + label
1171:                                    + ")");
1172:                ///CLOVER:ON
1173:
1174:                if (mVisit) {
1175:                    mMethodVisitor.visitLabel(label);
1176:                }
1177:
1178:                if (mAdapt) {
1179:                    mLabelContext = mTypes.nextLabelTypes();
1180:                }
1181:            }
1182:
1183:            /**
1184:             * Visits a TABLESWITCH instruction.
1185:             *
1186:             * @param min the minimum key value.
1187:             * @param max the maximum key value.
1188:             * @param dflt beginning of the default handler block.
1189:             * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
1190:             *      beginning of the handler block for the <tt>min + i</tt> key.
1191:             */
1192:            public void visitTableSwitchInsn(int min, int max, Label dflt,
1193:                    Label[] labels) {
1194:                ///CLOVER:OFF
1195:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1196:                    ContinuationDebug.LOGGER
1197:                            .finest(" Code:visitTableSwitchInsn    ("
1198:                                    + min
1199:                                    + ", "
1200:                                    + max
1201:                                    + ", "
1202:                                    + dflt
1203:                                    + ", "
1204:                                    + (null == labels ? null
1205:                                            : join(labels, ",")) + ")");
1206:                ///CLOVER:ON
1207:
1208:                if (mVisit) {
1209:                    mMethodVisitor.visitTableSwitchInsn(min, max, dflt, labels);
1210:                }
1211:            }
1212:
1213:            /**
1214:             * Visits the maximum stack size and the maximum number of local variables of
1215:             * the method.
1216:             *
1217:             * @param maxStack maximum stack size of the method.
1218:             * @param maxLocals maximum number of local variables for the method.
1219:             */
1220:            public void visitMaxs(int maxStack, int maxLocals) {
1221:                ///CLOVER:OFF
1222:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1223:                    ContinuationDebug.LOGGER
1224:                            .finest(" Code:visitMaxs               ("
1225:                                    + maxStack + ", " + maxLocals + ")");
1226:                ///CLOVER:ON
1227:
1228:                if (mVisit) {
1229:                    mMethodVisitor.visitMaxs(maxStack, maxLocals);
1230:                }
1231:            }
1232:
1233:            /**
1234:             * Visits a local variable declaration.
1235:             *
1236:             * @param name the name of a local variable.
1237:             * @param desc the type descriptor of this local variable.
1238:             * @param signature the type signature of this local variable. May be
1239:             *      <tt>null</tt> if the local variable type does not use generic types.
1240:             * @param start the first instruction corresponding to the scope of this
1241:             *      local variable (inclusive).
1242:             * @param end the last instruction corresponding to the scope of this
1243:             *      local variable (exclusive).
1244:             * @param index the local variable's index.
1245:             * @throws IllegalArgumentException if one of the labels has not already been
1246:             *      visited by this visitor (by the {@link #visitLabel visitLabel}
1247:             *      method).
1248:             */
1249:            public void visitLocalVariable(String name, String desc,
1250:                    String signature, Label start, Label end, int index) {
1251:                ///CLOVER:OFF
1252:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1253:                    ContinuationDebug.LOGGER
1254:                            .finest(" Code:visitLocalVariable      (\"" + name
1255:                                    + "\", \"" + desc + ", \"" + signature
1256:                                    + "\", " + start + ", " + end + ", "
1257:                                    + index + ")");
1258:                ///CLOVER:ON
1259:
1260:                if (mVisit) {
1261:                    mMethodVisitor.visitLocalVariable(name, desc, signature,
1262:                            start, end, index);
1263:                }
1264:            }
1265:
1266:            /**
1267:             * Visits a line number declaration.
1268:             *
1269:             * @param line a line number. This number refers to the source file
1270:             *      from which the class was compiled.
1271:             * @param start the first instruction corresponding to this line number.
1272:             * @throws IllegalArgumentException if <tt>start</tt> has not already been
1273:             *      visited by this visitor (by the {@link #visitLabel visitLabel}
1274:             *      method).
1275:             */
1276:            public void visitLineNumber(int line, Label start) {
1277:                ///CLOVER:OFF
1278:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1279:                    ContinuationDebug.LOGGER
1280:                            .finest(" Code:visitLineNumber         (" + line
1281:                                    + ", " + start + ")");
1282:                ///CLOVER:ON
1283:
1284:                if (mVisit) {
1285:                    mMethodVisitor.visitLineNumber(line, start);
1286:                }
1287:            }
1288:
1289:            /**
1290:             * Visits a non standard attribute of the code. This method must visit only
1291:             * the first attribute in the given attribute list.
1292:             *
1293:             * @param attr a non standard code attribute. Must not be <tt>null</tt>.
1294:             */
1295:            public void visitAttribute(Attribute attr) {
1296:                ///CLOVER:OFF
1297:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1298:                    ContinuationDebug.LOGGER
1299:                            .finest(" Code:visitAttribute          (" + attr
1300:                                    + ")");
1301:                ///CLOVER:ON
1302:
1303:                if (mVisit) {
1304:                    mMethodVisitor.visitAttribute(attr);
1305:                }
1306:            }
1307:
1308:            public void visitCode() {
1309:                ///CLOVER:OFF
1310:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1311:                    ContinuationDebug.LOGGER
1312:                            .finest(" Code:visitCode               ()");
1313:                ///CLOVER:ON
1314:
1315:                if (mVisit) {
1316:                    mMethodVisitor.visitCode();
1317:                }
1318:            }
1319:
1320:            public AnnotationVisitor visitAnnotationDefault() {
1321:                ///CLOVER:OFF
1322:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1323:                    ContinuationDebug.LOGGER
1324:                            .finest(" Code:visitAnnotationDefault  ()");
1325:                ///CLOVER:ON
1326:
1327:                if (mVisit) {
1328:                    return mMethodVisitor.visitAnnotationDefault();
1329:                }
1330:
1331:                return mAnnotationVisitor;
1332:            }
1333:
1334:            public AnnotationVisitor visitAnnotation(String desc,
1335:                    boolean visible) {
1336:                ///CLOVER:OFF
1337:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1338:                    ContinuationDebug.LOGGER
1339:                            .finest(" Code:visitAnnotation         (\"" + desc
1340:                                    + "\", " + visible + ")");
1341:                ///CLOVER:ON
1342:
1343:                if (mVisit) {
1344:                    return mMethodVisitor.visitAnnotation(desc, visible);
1345:                }
1346:
1347:                return mAnnotationVisitor;
1348:            }
1349:
1350:            public AnnotationVisitor visitParameterAnnotation(int parameter,
1351:                    String desc, boolean visible) {
1352:                ///CLOVER:OFF
1353:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1354:                    ContinuationDebug.LOGGER
1355:                            .finest(" Code:visitAnnotation         ("
1356:                                    + parameter + ", \"" + desc + "\", "
1357:                                    + visible + ")");
1358:                ///CLOVER:ON
1359:
1360:                if (mVisit) {
1361:                    return mMethodVisitor.visitParameterAnnotation(parameter,
1362:                            desc, visible);
1363:                }
1364:
1365:                return mAnnotationVisitor;
1366:            }
1367:
1368:            public void visitEnd() {
1369:                ///CLOVER:OFF
1370:                if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST))
1371:                    ContinuationDebug.LOGGER
1372:                            .finest(" Code:visitEnd                ()");
1373:                ///CLOVER:ON
1374:
1375:                if (mVisit) {
1376:                    mMethodVisitor.visitEnd();
1377:                }
1378:            }
1379:
1380:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.