Source Code Cross Referenced for TransparencyClassAdapter.java in  » Net » Terracotta » com » tc » object » bytecode » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » Terracotta » com.tc.object.bytecode 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
0003:         * notice. All rights reserved.
0004:         */
0005:        package com.tc.object.bytecode;
0006:
0007:        import com.tc.asm.ClassVisitor;
0008:        import com.tc.asm.FieldVisitor;
0009:        import com.tc.asm.Label;
0010:        import com.tc.asm.MethodVisitor;
0011:        import com.tc.asm.Type;
0012:        import com.tc.aspectwerkz.exception.DefinitionException;
0013:        import com.tc.aspectwerkz.reflect.ClassInfo;
0014:        import com.tc.aspectwerkz.reflect.FieldInfo;
0015:        import com.tc.aspectwerkz.reflect.MemberInfo;
0016:        import com.tc.logging.TCLogger;
0017:        import com.tc.logging.TCLogging;
0018:        import com.tc.object.Portability;
0019:        import com.tc.object.config.ConfigLockLevel;
0020:        import com.tc.object.config.LockDefinition;
0021:        import com.tc.object.config.TransparencyClassSpec;
0022:        import com.tc.object.lockmanager.api.LockLevel;
0023:        import com.tc.object.logging.InstrumentationLogger;
0024:        import com.tc.text.Banner;
0025:        import com.tc.util.Assert;
0026:
0027:        import java.lang.reflect.Modifier;
0028:        import java.util.HashSet;
0029:        import java.util.Set;
0030:
0031:        /**
0032:         * @author steve
0033:         */
0034:        public class TransparencyClassAdapter extends ClassAdapterBase {
0035:            private static final TCLogger logger = TCLogging
0036:                    .getLogger(TransparencyClassAdapter.class);
0037:
0038:            private final Set doNotInstrument = new HashSet();
0039:            private final PhysicalClassAdapterLogger physicalClassLogger;
0040:            private final InstrumentationLogger instrumentationLogger;
0041:
0042:            public TransparencyClassAdapter(ClassInfo classInfo,
0043:                    TransparencyClassSpec spec, final ClassVisitor cv,
0044:                    ManagerHelper mgrHelper,
0045:                    InstrumentationLogger instrumentationLogger,
0046:                    ClassLoader caller, Portability portability) {
0047:                super (classInfo, spec, cv, mgrHelper, caller, portability);
0048:                this .instrumentationLogger = instrumentationLogger;
0049:                this .physicalClassLogger = new PhysicalClassAdapterLogger(
0050:                        logger);
0051:            }
0052:
0053:            protected void basicVisit(final int version, final int access,
0054:                    final String name, String signature,
0055:                    final String super ClassName, final String[] interfaces) {
0056:
0057:                try {
0058:                    logger.debug("ADAPTING CLASS: " + name);
0059:                    super .basicVisit(version, access, name, signature,
0060:                            super ClassName, interfaces);
0061:                    getTransparencyClassSpec().createClassSupportMethods(cv);
0062:                } catch (RuntimeException e) {
0063:                    handleInstrumentationException(e);
0064:                    throw e;
0065:                } catch (Error e) {
0066:                    handleInstrumentationException(e);
0067:                    throw e;
0068:                }
0069:            }
0070:
0071:            private void handleInstrumentationException(Throwable e) {
0072:                logger.fatal(e);
0073:                logger.fatal("Calling System.exit(1)");
0074:                System.exit(1);
0075:            }
0076:
0077:            private boolean isRoot(int access, String fieldName) {
0078:                try {
0079:                    FieldInfo fieldInfo = spec.getFieldInfo(fieldName);
0080:                    boolean isRoot = fieldInfo == null ? false
0081:                            : getTransparencyClassSpec().isRootInThisClass(
0082:                                    fieldInfo);
0083:                    boolean isTransient = getTransparencyClassSpec()
0084:                            .isTransient(access, spec.getClassInfo(), fieldName);
0085:                    if (isTransient && isRoot) {
0086:                        if (instrumentationLogger.transientRootWarning()) {
0087:                            instrumentationLogger.transientRootWarning(
0088:                                    this .spec.getClassNameDots(), fieldName);
0089:                        }
0090:                    }
0091:                    return isRoot;
0092:                } catch (RuntimeException e) {
0093:                    handleInstrumentationException(e);
0094:                    throw e;
0095:                } catch (Error e) {
0096:                    handleInstrumentationException(e);
0097:                    throw e;
0098:                }
0099:            }
0100:
0101:            private String rootNameFor(String className, String fieldName) {
0102:                try {
0103:                    return getTransparencyClassSpec().rootNameFor(
0104:                            spec.getFieldInfo(fieldName));
0105:                } catch (RuntimeException e) {
0106:                    handleInstrumentationException(e);
0107:                    throw e;
0108:                } catch (Error e) {
0109:                    handleInstrumentationException(e);
0110:                    throw e;
0111:                }
0112:            }
0113:
0114:            protected FieldVisitor basicVisitField(final int access,
0115:                    final String name, final String desc, String signature,
0116:                    final Object value) {
0117:
0118:                FieldVisitor fieldVisitor = null;
0119:                try {
0120:
0121:                    if ((spec.isClassPortable() && spec.isPhysical() && !ByteCodeUtil
0122:                            .isTCSynthetic(name))
0123:                            || (spec.isClassAdaptable() && isRoot(access, name))) {
0124:                        // include the field, but remove final modifier for *most* fields
0125:                        if ((Modifier.isStatic(access) && !isRoot(access, name))
0126:                                || isMagicSerializationField(access, name, desc)) {
0127:                            fieldVisitor = cv.visitField(access, name, desc,
0128:                                    signature, value);
0129:                        } else {
0130:                            fieldVisitor = cv.visitField(~Modifier.FINAL
0131:                                    & access, name, desc, signature, value);
0132:                        }
0133:                        generateGettersSetters(access, name, desc, Modifier
0134:                                .isStatic(access));
0135:                    } else {
0136:                        fieldVisitor = cv.visitField(access, name, desc,
0137:                                signature, value);
0138:                    }
0139:                } catch (RuntimeException e) {
0140:                    e.printStackTrace();
0141:                    handleInstrumentationException(e);
0142:                } catch (Error e) {
0143:                    handleInstrumentationException(e);
0144:                    throw e;
0145:                }
0146:                return fieldVisitor;
0147:            }
0148:
0149:            private static boolean isStatic(int access) {
0150:                return Modifier.isStatic(access);
0151:            }
0152:
0153:            private static boolean isFinal(int access) {
0154:                return Modifier.isFinal(access);
0155:            }
0156:
0157:            private static boolean isPrivate(int access) {
0158:                return Modifier.isPrivate(access);
0159:            }
0160:
0161:            private boolean isMagicSerializationField(int access,
0162:                    String fieldName, String fieldDesc) {
0163:                // this method tests if the given field is the one the magic fields used by java serialization. If it is, we should
0164:                // not change any details about this field
0165:
0166:                boolean isStatic = isStatic(access);
0167:                boolean isFinal = isFinal(access);
0168:                boolean isPrivate = isPrivate(access);
0169:
0170:                if (isStatic && isFinal) {
0171:                    if ("J".equals(fieldDesc)
0172:                            && "serialVersionUID".equals(fieldName)) {
0173:                        return true;
0174:                    }
0175:                    if (isPrivate && "serialPersistentFields".equals(fieldName)
0176:                            && "[Ljava/io/ObjectStreamField;".equals(fieldDesc)) {
0177:                        return true;
0178:                    }
0179:                }
0180:
0181:                return false;
0182:            }
0183:
0184:            private void generateGettersSetters(final int fieldAccess,
0185:                    final String name, final String desc, boolean isStatic) {
0186:                boolean isTransient = getTransparencyClassSpec().isTransient(
0187:                        fieldAccess, spec.getClassInfo(), name);
0188:                // Plain getter and setters are generated for transient fields as other instrumented classes might call them.
0189:                boolean createPlainAccessors = isTransient && !isStatic;
0190:                boolean createInstrumentedAccessors = !isTransient && !isStatic;
0191:                boolean createRootAccessors = isRoot(fieldAccess, name);
0192:
0193:                int methodAccess = fieldAccess & (~ACC_TRANSIENT);
0194:                methodAccess &= (~ACC_FINAL); // remove final modifier since variable might be shadowed
0195:                methodAccess &= (~ACC_VOLATILE);
0196:                methodAccess |= ACC_SYNTHETIC;
0197:
0198:                if (createRootAccessors) {
0199:                    createRootGetter(methodAccess, name, desc);
0200:                } else if (createInstrumentedAccessors) {
0201:                    if (!ByteCodeUtil.isPrimitive(Type.getType(desc))) {
0202:                        createInstrumentedGetter(methodAccess, fieldAccess,
0203:                                name, desc);
0204:                    } else {
0205:                        createPlainGetter(methodAccess, fieldAccess, name, desc);
0206:                    }
0207:                } else if (createPlainAccessors) {
0208:                    createPlainGetter(methodAccess, fieldAccess, name, desc);
0209:                }
0210:
0211:                if (createInstrumentedAccessors || createRootAccessors) {
0212:                    createInstrumentedSetter(methodAccess, fieldAccess, name,
0213:                            desc);
0214:                } else if (createPlainAccessors) {
0215:                    createPlainSetter(methodAccess, fieldAccess, name, desc);
0216:                }
0217:            }
0218:
0219:            private boolean isPrimitive(Type t) {
0220:                return ByteCodeUtil.isPrimitive(t);
0221:            }
0222:
0223:            private MethodVisitor ignoreMethodIfNeeded(int access, String name,
0224:                    final String desc, String signature,
0225:                    final String[] exceptions, MemberInfo memberInfo) {
0226:                if (name.startsWith(ByteCodeUtil.TC_METHOD_PREFIX)
0227:                        || doNotInstrument.contains(name + desc)
0228:                        || getTransparencyClassSpec().doNotInstrument(name)) {
0229:                    if (!getTransparencyClassSpec().hasCustomMethodAdapter(
0230:                            memberInfo)) {
0231:                        physicalClassLogger.logVisitMethodIgnoring(name, desc);
0232:                        return cv.visitMethod(access, name, desc, signature,
0233:                                exceptions);
0234:                    }
0235:                }
0236:                return null;
0237:            }
0238:
0239:            protected MethodVisitor basicVisitMethod(int access, String name,
0240:                    final String desc, String signature,
0241:                    final String[] exceptions) {
0242:                String originalName = name;
0243:                MethodVisitor mv = null;
0244:
0245:                try {
0246:                    physicalClassLogger.logVisitMethodBegin(access, name, desc,
0247:                            signature, exceptions);
0248:
0249:                    MemberInfo memberInfo = getInstrumentationSpec()
0250:                            .getMethodInfo(access, name, desc);
0251:
0252:                    mv = ignoreMethodIfNeeded(access, name, desc, signature,
0253:                            exceptions, memberInfo);
0254:                    if (mv != null) {
0255:                        return mv;
0256:                    }
0257:
0258:                    LockDefinition[] locks = getTransparencyClassSpec()
0259:                            .lockDefinitionsFor(memberInfo);
0260:                    LockDefinition ld = getTransparencyClassSpec()
0261:                            .getAutoLockDefinition(locks);
0262:                    boolean isAutolock = (ld != null);
0263:                    int lockLevel = -1;
0264:                    if (isAutolock) {
0265:                        lockLevel = ld.getLockLevelAsInt();
0266:                        if (instrumentationLogger.lockInsertion()) {
0267:                            instrumentationLogger.autolockInserted(this .spec
0268:                                    .getClassNameDots(), name, desc, ld);
0269:                        }
0270:                    }
0271:                    boolean isAutoReadLock = isAutolock
0272:                            && (lockLevel == LockLevel.READ);
0273:
0274:                    if (isAutoSynchronized(ld) && !"<init>".equals(name)) {
0275:                        access |= ACC_SYNCHRONIZED;
0276:                    }
0277:
0278:                    boolean isLockMethod = isAutolock
0279:                            && Modifier.isSynchronized(access)
0280:                            && !Modifier.isStatic(access);
0281:                    physicalClassLogger.logVisitMethodCheckIsLockMethod();
0282:
0283:                    if (!isLockMethod || spec.isClassAdaptable()) {
0284:                        isLockMethod = (getTransparencyClassSpec()
0285:                                .getNonAutoLockDefinition(locks) != null);
0286:                    }
0287:
0288:                    // handle lock method by re-writing the original method as a wrapper method and rename the original method.
0289:                    if (isLockMethod && !"<init>".equals(name)) {
0290:                        physicalClassLogger
0291:                                .logVisitMethodCreateLockMethod(name);
0292:                        // This method is a lock method.
0293:                        Assert.assertNotNull(locks);
0294:                        Assert.eval(locks.length > 0 || isLockMethod);
0295:                        createLockMethod(access, name, desc, signature,
0296:                                exceptions, locks, isAutoReadLock);
0297:
0298:                        logCustomerLockMethod(name, desc, locks);
0299:                        name = ByteCodeUtil.METHOD_RENAME_PREFIX + name;
0300:                        access |= ACC_PRIVATE;
0301:                        access &= (~ACC_PUBLIC);
0302:                        access &= (~ACC_PROTECTED);
0303:                        if (isAutoReadLock) {
0304:                            access &= (~ACC_SYNCHRONIZED);
0305:                        }
0306:                    } else {
0307:                        physicalClassLogger.logVisitMethodNotALockMethod(
0308:                                access, this .spec.getClassNameDots(), name,
0309:                                desc, exceptions);
0310:                    }
0311:
0312:                    // Visit the original method by either using a custom adapter or a TransparencyCodeAdapter or both.
0313:                    if (getTransparencyClassSpec().hasCustomMethodAdapter(
0314:                            memberInfo)) {
0315:                        MethodAdapter ma = getTransparencyClassSpec()
0316:                                .customMethodAdapterFor(
0317:                                        spec.getManagerHelper(), access, name,
0318:                                        originalName, desc, signature,
0319:                                        exceptions, instrumentationLogger,
0320:                                        memberInfo);
0321:                        mv = ma.adapt(cv);
0322:
0323:                        if (!ma.doesOriginalNeedAdapting())
0324:                            return mv;
0325:                    }
0326:
0327:                    if (mv == null) {
0328:                        mv = cv.visitMethod(access, name, desc, signature,
0329:                                exceptions);
0330:                    }
0331:
0332:                    return mv == null ? null : new TransparencyCodeAdapter(
0333:                            spec, isAutolock, lockLevel, mv, memberInfo,
0334:                            originalName);
0335:                } catch (RuntimeException e) {
0336:                    handleInstrumentationException(e);
0337:                    throw e;
0338:                } catch (Error e) {
0339:                    handleInstrumentationException(e);
0340:                    throw e;
0341:                }
0342:            }
0343:
0344:            private boolean isAutoSynchronized(LockDefinition ld) {
0345:                if (ld == null) {
0346:                    return false;
0347:                }
0348:
0349:                ConfigLockLevel lockLevel = ld.getLockLevel();
0350:                return ConfigLockLevel.AUTO_SYNCHRONIZED_READ.equals(lockLevel)
0351:                        || ConfigLockLevel.AUTO_SYNCHRONIZED_WRITE
0352:                                .equals(lockLevel)
0353:                        || ConfigLockLevel.AUTO_SYNCHRONIZED_CONCURRENT
0354:                                .equals(lockLevel)
0355:                        || ConfigLockLevel.AUTO_SYNCHRONIZED_SYNCHRONOUS_WRITE
0356:                                .equals(lockLevel);
0357:            }
0358:
0359:            // protected void basicVisitEnd() {
0360:            // // if adaptee has DMI
0361:            // boolean hasCustomMethodAdapter = getTransparencyClassSpec().hasCustomMethodAdapter(access, originalName, desc,
0362:            // exceptions);
0363:            // super.basicVisitEnd();
0364:            // }
0365:
0366:            private void logCustomerLockMethod(String name, final String desc,
0367:                    LockDefinition[] locks) {
0368:                if (instrumentationLogger.lockInsertion()) {
0369:                    instrumentationLogger.lockInserted(this .spec
0370:                            .getClassNameDots(), name, desc, locks);
0371:                }
0372:            }
0373:
0374:            private void createLockMethod(int access, String name, String desc,
0375:                    String signature, final String[] exceptions,
0376:                    LockDefinition[] locks, boolean skipLocalJVMLock) {
0377:                try {
0378:                    physicalClassLogger.logCreateLockMethodBegin(access, name,
0379:                            desc, signature, exceptions, locks);
0380:                    doNotInstrument.add(name + desc);
0381:                    recreateMethod(access, name, desc, signature, exceptions,
0382:                            locks, skipLocalJVMLock);
0383:                    if (skipLocalJVMLock) {
0384:                        access |= ACC_PRIVATE;
0385:                        access &= (~ACC_PUBLIC);
0386:                        access &= (~ACC_PROTECTED);
0387:
0388:                        createSyncMethod(access, name, desc, signature,
0389:                                exceptions);
0390:                    }
0391:
0392:                } catch (RuntimeException e) {
0393:                    handleInstrumentationException(e);
0394:                    throw e;
0395:                } catch (Error e) {
0396:                    handleInstrumentationException(e);
0397:                    throw e;
0398:                }
0399:            }
0400:
0401:            private String getTCSyncMethodName(String name) {
0402:                return ByteCodeUtil.SYNC_METHOD_RENAME_PREFIX + name;
0403:            }
0404:
0405:            private void createSyncMethod(int access, String name, String desc,
0406:                    String signature, final String[] exceptions) {
0407:                Type returnType = Type.getReturnType(desc);
0408:                // access should have the synchronized modifier
0409:                MethodVisitor mv = cv.visitMethod(access,
0410:                        getTCSyncMethodName(name), desc, signature, exceptions);
0411:                mv.visitCode();
0412:                Label l0 = new Label();
0413:                mv.visitLabel(l0);
0414:                callRenamedMethod(access & (~Modifier.SYNCHRONIZED), name,
0415:                        desc, mv);
0416:                Label l1 = new Label();
0417:                mv.visitLabel(l1);
0418:                mv.visitInsn(returnType.getOpcode(IRETURN));
0419:                Label l2 = new Label();
0420:                mv.visitLabel(l2);
0421:                mv.visitLocalVariable("this", "L" + spec.getClassNameSlashes()
0422:                        + ";", null, l0, l2, 0);
0423:                mv.visitMaxs(1, 1);
0424:                mv.visitEnd();
0425:            }
0426:
0427:            private void recreateMethod(int access, String name, String desc,
0428:                    String signature, final String[] exceptions,
0429:                    LockDefinition[] locks, boolean skipLocalJVMLock) {
0430:                Type returnType = Type.getReturnType(desc);
0431:                physicalClassLogger.logCreateLockMethodVoidBegin(access, name,
0432:                        desc, signature, exceptions, locks);
0433:                MethodVisitor c = cv.visitMethod(access
0434:                        & (~Modifier.SYNCHRONIZED), name, desc, signature,
0435:                        exceptions);
0436:
0437:                Label l1 = new Label();
0438:                if (skipLocalJVMLock) {
0439:                    ByteCodeUtil.pushThis(c);
0440:                    c.visitMethodInsn(INVOKESTATIC,
0441:                            "com/tc/object/bytecode/ManagerUtil",
0442:                            "isDsoMonitored", "(Ljava/lang/Object;)Z");
0443:                    c.visitJumpInsn(IFEQ, l1);
0444:                }
0445:
0446:                if (returnType.getSort() == Type.VOID) {
0447:                    addDsoLockMethodInsnVoid(access, name, desc, signature,
0448:                            exceptions, locks, c);
0449:                } else {
0450:                    addDsoLockMethodInsnReturn(access, name, desc, signature,
0451:                            exceptions, locks, returnType, c);
0452:                }
0453:
0454:                if (skipLocalJVMLock) {
0455:                    c.visitLabel(l1);
0456:                    // access should have the synchronized modifier
0457:                    callRenamedMethod(access, "sync" + "_" + name, desc, c);
0458:
0459:                    c.visitInsn(returnType.getOpcode(IRETURN));
0460:                }
0461:
0462:                c.visitMaxs(0, 0);
0463:                c.visitEnd();
0464:            }
0465:
0466:            private int addBooleanLocalVariablesIfMoreThanOneLock(int access,
0467:                    String desc, LockDefinition[] locks, MethodVisitor c,
0468:                    int[] localBooleanVariables) {
0469:                int nextLocalVariable = ByteCodeUtil
0470:                        .getFirstLocalVariableOffset(access, desc);
0471:                if (locks.length > 1) {
0472:                    for (int i = 0; i < locks.length; i++) {
0473:                        localBooleanVariables[i] = nextLocalVariable;
0474:                        ByteCodeUtil.pushDefaultValue(localBooleanVariables[i],
0475:                                c, Type.BOOLEAN_TYPE);
0476:                        nextLocalVariable += Type.BOOLEAN_TYPE.getSize();
0477:                    }
0478:                }
0479:                return nextLocalVariable;
0480:            }
0481:
0482:            private void startDsoLockTryBlock(int access, String name,
0483:                    String desc, LockDefinition[] locks, MethodVisitor c,
0484:                    int[] localBooleanVariables, Label startTryBlockLabel) {
0485:                if (locks.length > 1) {
0486:                    c.visitLabel(startTryBlockLabel);
0487:                    callTCBeginWithLocks(access, name, desc, locks, c,
0488:                            localBooleanVariables);
0489:                } else {
0490:                    callTCBeginWithLocks(access, name, desc, locks, c,
0491:                            localBooleanVariables);
0492:                    c.visitLabel(startTryBlockLabel);
0493:                }
0494:            }
0495:
0496:            /**
0497:             * Creates a tc lock method for the given method that returns void.
0498:             */
0499:            private void addDsoLockMethodInsnVoid(int access, String name,
0500:                    String desc, String signature, final String[] exceptions,
0501:                    LockDefinition[] locks, MethodVisitor c) {
0502:                int[] localBooleanVariables = new int[locks.length];
0503:                int localVariableOffset = addBooleanLocalVariablesIfMoreThanOneLock(
0504:                        access, desc, locks, c, localBooleanVariables);
0505:
0506:                try {
0507:
0508:                    Label l0 = new Label();
0509:                    startDsoLockTryBlock(access, name, desc, locks, c,
0510:                            localBooleanVariables, l0);
0511:                    callRenamedMethod(access, name, desc, c);
0512:                    // This label creation has something to do with try/finally
0513:                    Label l1 = new Label();
0514:                    c.visitJumpInsn(GOTO, l1);
0515:                    Label l2 = new Label();
0516:                    c.visitLabel(l2);
0517:                    c.visitVarInsn(ASTORE, 1 + localVariableOffset);
0518:                    Label l3 = new Label();
0519:                    c.visitJumpInsn(JSR, l3);
0520:                    c.visitVarInsn(ALOAD, 1 + localVariableOffset);
0521:                    c.visitInsn(ATHROW);
0522:                    c.visitLabel(l3);
0523:                    c.visitVarInsn(ASTORE, 0 + localVariableOffset);
0524:                    callTCCommit(access, name, desc, locks, c,
0525:                            localBooleanVariables);
0526:                    c.visitVarInsn(RET, 0 + localVariableOffset);
0527:                    c.visitLabel(l1);
0528:                    c.visitJumpInsn(JSR, l3);
0529:                    Label l4 = new Label();
0530:                    c.visitLabel(l4);
0531:                    c.visitInsn(RETURN);
0532:                    c.visitTryCatchBlock(l0, l2, l2, null);
0533:                    c.visitTryCatchBlock(l1, l4, l2, null);
0534:                } catch (RuntimeException e) {
0535:                    handleInstrumentationException(e);
0536:                } catch (Error e) {
0537:                    handleInstrumentationException(e);
0538:                    throw e;
0539:                }
0540:            }
0541:
0542:            private void handleInstrumentationException(RuntimeException e) {
0543:                // XXX: Yucky.
0544:                if (e instanceof  DefinitionException) {
0545:                    logger.fatal(e.getLocalizedMessage());
0546:                } else {
0547:                    logger.fatal(e);
0548:                }
0549:
0550:                e.printStackTrace(System.err);
0551:                System.err.flush();
0552:                String msg = "Error detected -- Calling System.exit(1)";
0553:                Banner.errorBanner(msg);
0554:
0555:                logger.fatal(msg);
0556:                System.exit(1);
0557:            }
0558:
0559:            private void callRenamedMethod(int callingMethodModifier,
0560:                    String name, String desc, MethodVisitor c) {
0561:                // Call the renamed original method.
0562:                ByteCodeUtil.prepareStackForMethodCall(callingMethodModifier,
0563:                        desc, c);
0564:                if (Modifier.isStatic(callingMethodModifier)) {
0565:                    c.visitMethodInsn(INVOKESTATIC, spec.getClassNameSlashes(),
0566:                            ByteCodeUtil.METHOD_RENAME_PREFIX + name, desc);
0567:                } else {
0568:                    c.visitMethodInsn(INVOKESPECIAL,
0569:                            spec.getClassNameSlashes(),
0570:                            ByteCodeUtil.METHOD_RENAME_PREFIX + name, desc);
0571:                }
0572:            }
0573:
0574:            /**
0575:             * Creates a tc lock method for the given method that returns a value (doesn't return void).
0576:             */
0577:            private void addDsoLockMethodInsnReturn(int access, String name,
0578:                    String desc, String signature, final String[] exceptions,
0579:                    LockDefinition[] locks, Type returnType, MethodVisitor c) {
0580:                int[] localBooleanVariables = new int[locks.length];
0581:                int localVariableOffset = addBooleanLocalVariablesIfMoreThanOneLock(
0582:                        access, desc, locks, c, localBooleanVariables);
0583:
0584:                try {
0585:                    Label l0 = new Label();
0586:                    startDsoLockTryBlock(access, name, desc, locks, c,
0587:                            localBooleanVariables, l0);
0588:                    callRenamedMethod(access, name, desc, c);
0589:                    c.visitVarInsn(returnType.getOpcode(ISTORE),
0590:                            2 + localVariableOffset);
0591:                    Label l1 = new Label();
0592:                    c.visitJumpInsn(JSR, l1);
0593:                    Label l2 = new Label();
0594:                    c.visitLabel(l2);
0595:                    c.visitVarInsn(returnType.getOpcode(ILOAD),
0596:                            2 + localVariableOffset);
0597:                    c.visitInsn(returnType.getOpcode(IRETURN));
0598:                    Label l3 = new Label();
0599:                    c.visitLabel(l3);
0600:                    c.visitVarInsn(ASTORE, 1 + localVariableOffset);
0601:                    c.visitJumpInsn(JSR, l1);
0602:                    c.visitVarInsn(ALOAD, 1 + localVariableOffset);
0603:                    c.visitInsn(ATHROW);
0604:                    c.visitLabel(l1);
0605:                    c.visitVarInsn(ASTORE, 0 + localVariableOffset);
0606:                    callTCCommit(access, name, desc, locks, c,
0607:                            localBooleanVariables);
0608:                    c.visitVarInsn(RET, 0 + localVariableOffset);
0609:                    c.visitTryCatchBlock(l0, l2, l3, null);
0610:                    // c.visitMaxs(0, 0);
0611:                } catch (RuntimeException e) {
0612:                    handleInstrumentationException(e);
0613:                } catch (Error e) {
0614:                    handleInstrumentationException(e);
0615:                    throw e;
0616:                }
0617:
0618:            }
0619:
0620:            private void callTCBeginWithLocks(int access, String name,
0621:                    String desc, LockDefinition[] locks, MethodVisitor c,
0622:                    int[] localBooleanVariables) {
0623:                physicalClassLogger.logCallTCBeginWithLocksStart(access, name,
0624:                        desc, locks, c);
0625:                for (int i = 0; i < locks.length; i++) {
0626:                    LockDefinition lock = locks[i];
0627:                    if (lock.isAutolock() && spec.isClassPortable()) {
0628:                        physicalClassLogger.logCallTCBeginWithLocksAutolock();
0629:                        if (Modifier.isSynchronized(access)
0630:                                && !Modifier.isStatic(access)) {
0631:                            physicalClassLogger
0632:                                    .logCallTCBeginWithLocksAutolockSynchronized(
0633:                                            name, desc);
0634:                            callTCMonitorEnter(access, locks[i], c);
0635:                        } else {
0636:                            physicalClassLogger
0637:                                    .logCallTCBeginWithLocksAutolockNotSynchronized(
0638:                                            name, desc);
0639:                        }
0640:                    } else if (!lock.isAutolock()) {
0641:                        physicalClassLogger
0642:                                .logCallTCBeginWithLocksNoAutolock(lock);
0643:                        callTCBeginWithLock(lock, c);
0644:                    }
0645:                    if (locks.length > 1) {
0646:                        c.visitInsn(ICONST_1);
0647:                        c.visitVarInsn(ISTORE, localBooleanVariables[i]);
0648:                    }
0649:                }
0650:            }
0651:
0652:            private void callTCCommit(int access, String name, String desc,
0653:                    LockDefinition[] locks, MethodVisitor c,
0654:                    int[] localBooleanVariables) {
0655:                physicalClassLogger.logCallTCCommitBegin(access, name, desc,
0656:                        locks, c);
0657:                Label returnLabel = new Label();
0658:                for (int i = 0; i < locks.length; i++) {
0659:                    if (locks.length > 1) {
0660:                        c.visitVarInsn(ILOAD, localBooleanVariables[i]);
0661:                        c.visitJumpInsn(IFEQ, returnLabel);
0662:                    }
0663:                    LockDefinition lock = locks[i];
0664:                    if (lock.isAutolock() && spec.isClassPortable()) {
0665:                        if (Modifier.isSynchronized(access)
0666:                                && !Modifier.isStatic(access)) {
0667:                            callTCMonitorExit(access, c);
0668:                        }
0669:                    } else if (!lock.isAutolock()) {
0670:                        c.visitLdcInsn(ByteCodeUtil.generateNamedLockName(lock
0671:                                .getLockName()));
0672:                        spec.getManagerHelper().callManagerMethod("commitLock",
0673:                                c);
0674:                    }
0675:                }
0676:                c.visitLabel(returnLabel);
0677:            }
0678:
0679:            private void callTCCommitWithLockName(String lockName,
0680:                    MethodVisitor mv) {
0681:                mv.visitLdcInsn(lockName);
0682:                spec.getManagerHelper().callManagerMethod("commitLock", mv);
0683:            }
0684:
0685:            private void callTCBeginWithLock(LockDefinition lock,
0686:                    MethodVisitor c) {
0687:                c.visitLdcInsn(ByteCodeUtil.generateNamedLockName(lock
0688:                        .getLockName()));
0689:                c.visitLdcInsn(new Integer(lock.getLockLevelAsInt()));
0690:                spec.getManagerHelper().callManagerMethod("beginLock", c);
0691:            }
0692:
0693:            private void callTCBeginWithLockName(String lockName,
0694:                    int lockLevel, MethodVisitor mv) {
0695:                mv.visitLdcInsn(lockName);
0696:                mv.visitLdcInsn(new Integer(lockLevel));
0697:                spec.getManagerHelper().callManagerMethod("beginLock", mv);
0698:            }
0699:
0700:            private void callVolatileBegin(String fieldName, int lockLevel,
0701:                    MethodVisitor mv) {
0702:                getManaged(mv);
0703:                mv.visitLdcInsn(fieldName);
0704:                mv.visitIntInsn(BIPUSH, lockLevel);
0705:                spec.getManagerHelper().callManagerMethod("beginVolatile", mv);
0706:            }
0707:
0708:            private void callVolatileCommit(String fieldName, MethodVisitor mv) {
0709:                getManaged(mv);
0710:                mv.visitLdcInsn(fieldName);
0711:                spec.getManagerHelper().callManagerMethod("commitVolatile", mv);
0712:            }
0713:
0714:            private void createPlainGetter(int methodAccess, int fieldAccess,
0715:                    String name, String desc) {
0716:                boolean isVolatile = isVolatile(fieldAccess, name);
0717:
0718:                String gDesc = "()" + desc;
0719:                MethodVisitor gv = this .visitMethod(methodAccess, ByteCodeUtil
0720:                        .fieldGetterMethod(name), gDesc, null, null);
0721:                Type t = Type.getType(desc);
0722:
0723:                Label l4 = new Label();
0724:
0725:                if (isVolatile) {
0726:                    getManaged(gv);
0727:                    gv.visitInsn(DUP);
0728:                    gv.visitVarInsn(ASTORE, 2);
0729:                    gv.visitJumpInsn(IFNULL, l4);
0730:
0731:                    Label l0 = new Label();
0732:                    Label l1 = new Label();
0733:                    Label l2 = new Label();
0734:                    gv.visitTryCatchBlock(l0, l1, l2, null);
0735:                    gv.visitLabel(l0);
0736:
0737:                    callVolatileBegin(spec.getClassNameDots() + "." + name,
0738:                            LockLevel.READ, gv);
0739:
0740:                    Label l6 = new Label();
0741:                    gv.visitJumpInsn(JSR, l6);
0742:                    gv.visitLabel(l1);
0743:                    ByteCodeUtil.pushThis(gv);
0744:                    gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(),
0745:                            name, desc);
0746:                    gv.visitInsn(t.getOpcode(IRETURN));
0747:                    gv.visitLabel(l2);
0748:                    gv.visitVarInsn(ASTORE, 2);
0749:                    gv.visitJumpInsn(JSR, l6);
0750:                    gv.visitVarInsn(ALOAD, 2);
0751:                    gv.visitInsn(ATHROW);
0752:                    gv.visitLabel(l6);
0753:                    gv.visitVarInsn(ASTORE, 1);
0754:
0755:                    callVolatileCommit(spec.getClassNameDots() + "." + name, gv);
0756:                    gv.visitVarInsn(RET, 1);
0757:                }
0758:
0759:                gv.visitLabel(l4);
0760:                ByteCodeUtil.pushThis(gv);
0761:                gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), name,
0762:                        desc);
0763:                gv.visitInsn(t.getOpcode(IRETURN));
0764:
0765:                gv.visitMaxs(0, 0);
0766:            }
0767:
0768:            private void checkReturnObjectType(String fieldName,
0769:                    String rootName, String targetType, int loadVariableNumber,
0770:                    Label matchLabel, MethodVisitor mv) {
0771:                mv.visitVarInsn(ALOAD, loadVariableNumber);
0772:                mv.visitTypeInsn(INSTANCEOF, targetType);
0773:                mv.visitJumpInsn(IFNE, matchLabel);
0774:                mv.visitTypeInsn(NEW, "java/lang/ClassCastException");
0775:                mv.visitInsn(DUP);
0776:                mv.visitTypeInsn(NEW, "java/lang/StringBuffer");
0777:                mv.visitInsn(DUP);
0778:                mv.visitLdcInsn("The field '");
0779:                mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer",
0780:                        "<init>", "(Ljava/lang/String;)V");
0781:                mv.visitLdcInsn(fieldName);
0782:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0783:                        "append",
0784:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0785:                mv.visitLdcInsn("' with root name '");
0786:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0787:                        "append",
0788:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0789:                mv.visitLdcInsn(rootName);
0790:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0791:                        "append",
0792:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0793:                mv.visitLdcInsn("' cannot be assigned to a variable of type ");
0794:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0795:                        "append",
0796:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0797:                mv.visitLdcInsn(targetType);
0798:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0799:                        "append",
0800:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0801:                mv.visitLdcInsn(". This root has a type ");
0802:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0803:                        "append",
0804:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0805:                mv.visitVarInsn(ALOAD, loadVariableNumber);
0806:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
0807:                        "getClass", "()Ljava/lang/Class;");
0808:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName",
0809:                        "()Ljava/lang/String;");
0810:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0811:                        "append",
0812:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0813:                mv.visitLdcInsn(". ");
0814:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0815:                        "append",
0816:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0817:                mv
0818:                        .visitLdcInsn("Perhaps you have the same root name assigned more than once to variables of different types.");
0819:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0820:                        "append",
0821:                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
0822:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
0823:                        "toString", "()Ljava/lang/String;");
0824:                mv.visitMethodInsn(INVOKESPECIAL,
0825:                        "java/lang/ClassCastException", "<init>",
0826:                        "(Ljava/lang/String;)V");
0827:                mv.visitInsn(ATHROW);
0828:
0829:            }
0830:
0831:            private void createRootGetter(int methodAccess, String name,
0832:                    String desc) {
0833:                Type t = Type.getType(desc);
0834:                boolean isPrimitive = isPrimitive(t);
0835:                boolean isDSOFinal = isRootDSOFinal(name);
0836:
0837:                String rootName = rootNameFor(spec.getClassNameSlashes(), name);
0838:                String targetType = isPrimitive ? ByteCodeUtil
0839:                        .sortToWrapperName(t.getSort())
0840:                        : convertToCheckCastDesc(desc);
0841:
0842:                boolean isStatic = Modifier.isStatic(methodAccess);
0843:
0844:                Label l1 = new Label();
0845:                Label l3 = new Label();
0846:                Label l5 = new Label();
0847:                Label l6 = new Label();
0848:                Label l7 = new Label();
0849:                Label l8 = new Label();
0850:
0851:                try {
0852:                    MethodVisitor mv = cv.visitMethod(methodAccess,
0853:                            ByteCodeUtil.fieldGetterMethod(name), "()" + desc,
0854:                            null, null);
0855:
0856:                    if (isDSOFinal) {
0857:                        callGetFieldInsn(isStatic, name, desc, mv);
0858:                        if (isPrimitive) {
0859:                            addPrimitiveTypeZeroCompare(mv, t, l1);
0860:                        } else {
0861:                            mv.visitJumpInsn(IFNONNULL, l1);
0862:                        }
0863:                    }
0864:
0865:                    callTCBeginWithLockName(rootName, LockLevel.WRITE, mv);
0866:
0867:                    mv.visitLabel(l3);
0868:                    mv.visitLdcInsn(rootName);
0869:                    spec.getManagerHelper().callManagerMethod("lookupRoot", mv);
0870:                    mv.visitVarInsn(ASTORE, 1);
0871:
0872:                    mv.visitVarInsn(ALOAD, 1);
0873:                    mv.visitJumpInsn(IFNULL, l5);
0874:
0875:                    checkReturnObjectType(name, rootName, targetType, 1, l6, mv);
0876:
0877:                    mv.visitLabel(l6);
0878:                    callPutFieldInsn(isStatic, t, 1, name, desc, mv);
0879:                    mv.visitJumpInsn(GOTO, l5);
0880:
0881:                    mv.visitLabel(l7);
0882:                    mv.visitVarInsn(ASTORE, 3);
0883:                    mv.visitJumpInsn(JSR, l8);
0884:                    mv.visitVarInsn(ALOAD, 3);
0885:                    mv.visitInsn(ATHROW);
0886:
0887:                    mv.visitLabel(l8);
0888:                    mv.visitVarInsn(ASTORE, 2);
0889:                    callTCCommitWithLockName(rootName, mv);
0890:                    mv.visitVarInsn(RET, 2);
0891:
0892:                    mv.visitLabel(l5);
0893:                    mv.visitJumpInsn(JSR, l8);
0894:
0895:                    mv.visitLabel(l1);
0896:                    callGetFieldInsn(isStatic, name, desc, mv);
0897:                    mv.visitInsn(t.getOpcode(IRETURN));
0898:                    mv.visitTryCatchBlock(l3, l7, l7, null);
0899:                    mv.visitMaxs(0, 0);
0900:                } catch (RuntimeException e) {
0901:                    handleInstrumentationException(e);
0902:                } catch (Error e) {
0903:                    handleInstrumentationException(e);
0904:                    throw e;
0905:                }
0906:            }
0907:
0908:            private boolean isVolatile(int access, String fieldName) {
0909:                return getTransparencyClassSpec().isVolatile(access,
0910:                        spec.getClassInfo(), fieldName);
0911:            }
0912:
0913:            private void createInstrumentedGetter(int methodAccess,
0914:                    int fieldAccess, String name, String desc) {
0915:                try {
0916:                    Assert.eval(!getTransparencyClassSpec().isLogical());
0917:                    boolean isVolatile = isVolatile(fieldAccess, name);
0918:
0919:                    String gDesc = "()" + desc;
0920:                    MethodVisitor gv = this .visitMethod(methodAccess,
0921:                            ByteCodeUtil.fieldGetterMethod(name), gDesc, null,
0922:                            null);
0923:                    Type t = Type.getType(desc);
0924:
0925:                    getManaged(gv);
0926:                    gv.visitInsn(DUP);
0927:                    gv.visitVarInsn(ASTORE, 3);
0928:
0929:                    Label l0 = new Label();
0930:                    gv.visitJumpInsn(IFNULL, l0);
0931:
0932:                    if (isVolatile) {
0933:                        callVolatileBegin(spec.getClassNameDots() + '.' + name,
0934:                                LockLevel.READ, gv);
0935:                    }
0936:
0937:                    gv.visitVarInsn(ALOAD, 3);
0938:                    gv.visitMethodInsn(INVOKEINTERFACE,
0939:                            "com/tc/object/TCObject", "getResolveLock",
0940:                            "()Ljava/lang/Object;");
0941:                    gv.visitInsn(DUP);
0942:                    gv.visitVarInsn(ASTORE, 2);
0943:                    gv.visitInsn(MONITORENTER);
0944:
0945:                    Label l1 = new Label();
0946:                    gv.visitLabel(l1);
0947:
0948:                    gv.visitVarInsn(ALOAD, 0);
0949:                    gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(),
0950:                            name, desc);
0951:                    Label l5 = new Label();
0952:                    gv.visitJumpInsn(IFNONNULL, l5);
0953:                    gv.visitVarInsn(ALOAD, 3);
0954:                    gv.visitLdcInsn(spec.getClassNameDots() + '.' + name);
0955:                    gv.visitMethodInsn(INVOKEINTERFACE,
0956:                            "com/tc/object/TCObject", "resolveReference",
0957:                            "(Ljava/lang/String;)V");
0958:                    gv.visitLabel(l5);
0959:
0960:                    Label l2 = new Label();
0961:
0962:                    gv.visitVarInsn(ALOAD, 0);
0963:                    gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(),
0964:                            name, desc);
0965:                    gv.visitVarInsn(ALOAD, 2);
0966:
0967:                    gv.visitInsn(MONITOREXIT);
0968:                    if (isVolatile) {
0969:                        callVolatileCommit(
0970:                                spec.getClassNameDots() + "." + name, gv);
0971:                    }
0972:                    gv.visitInsn(ARETURN);
0973:                    gv.visitJumpInsn(GOTO, l0);
0974:
0975:                    gv.visitLabel(l2);
0976:                    gv.visitVarInsn(ALOAD, 2);
0977:
0978:                    gv.visitInsn(MONITOREXIT);
0979:                    if (isVolatile) {
0980:                        callVolatileCommit(
0981:                                spec.getClassNameDots() + "." + name, gv);
0982:                    }
0983:                    gv.visitInsn(ATHROW);
0984:
0985:                    gv.visitLabel(l0);
0986:                    gv.visitVarInsn(ALOAD, 0);
0987:                    gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(),
0988:                            name, desc);
0989:                    gv.visitInsn(t.getOpcode(IRETURN));
0990:
0991:                    gv.visitTryCatchBlock(l1, l2, l2, null);
0992:
0993:                    gv.visitMaxs(0, 0);
0994:                } catch (RuntimeException e) {
0995:                    handleInstrumentationException(e);
0996:                } catch (Error e) {
0997:                    handleInstrumentationException(e);
0998:                    throw e;
0999:                }
1000:            }
1001:
1002:            private void getManaged(MethodVisitor mv) {
1003:                mv.visitVarInsn(ALOAD, 0);
1004:                mv.visitMethodInsn(INVOKEVIRTUAL, spec.getClassNameSlashes(),
1005:                        MANAGED_METHOD, "()" + MANAGED_FIELD_TYPE);
1006:            }
1007:
1008:            private void createPlainSetter(int methodAccess, int fieldAccess,
1009:                    String name, String desc) {
1010:                boolean isVolatile = isVolatile(fieldAccess, name);
1011:
1012:                String sDesc = "(" + desc + ")V";
1013:                MethodVisitor scv = cv.visitMethod(methodAccess, ByteCodeUtil
1014:                        .fieldSetterMethod(name), sDesc, null, null);
1015:                Type t = Type.getType(desc);
1016:
1017:                Label l4 = new Label();
1018:
1019:                if (isVolatile) {
1020:                    getManaged(scv);
1021:                    scv.visitInsn(DUP);
1022:                    scv.visitVarInsn(ASTORE, 2);
1023:                    scv.visitJumpInsn(IFNULL, l4);
1024:
1025:                    Label l0 = new Label();
1026:                    Label l1 = new Label();
1027:                    Label l2 = new Label();
1028:                    scv.visitTryCatchBlock(l0, l1, l2, null);
1029:                    scv.visitLabel(l0);
1030:
1031:                    callVolatileBegin(spec.getClassNameDots() + "." + name,
1032:                            LockLevel.WRITE, scv);
1033:
1034:                    Label l6 = new Label();
1035:                    scv.visitJumpInsn(JSR, l6);
1036:                    scv.visitLabel(l1);
1037:                    ByteCodeUtil.pushThis(scv);
1038:                    scv.visitVarInsn(t.getOpcode(ILOAD), 1);
1039:
1040:                    scv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(),
1041:                            name, desc);
1042:                    scv.visitInsn(RETURN);
1043:                    scv.visitLabel(l2);
1044:                    scv.visitVarInsn(ASTORE, 2);
1045:                    scv.visitJumpInsn(JSR, l6);
1046:                    scv.visitVarInsn(ALOAD, 2);
1047:                    scv.visitInsn(ATHROW);
1048:                    scv.visitLabel(l6);
1049:                    scv.visitVarInsn(ASTORE, 1);
1050:                    callVolatileCommit(spec.getClassNameDots() + "." + name,
1051:                            scv);
1052:
1053:                    scv.visitVarInsn(RET, 1);
1054:                }
1055:
1056:                scv.visitLabel(l4);
1057:                ByteCodeUtil.pushThis(scv);
1058:                scv.visitVarInsn(t.getOpcode(ILOAD), 1);
1059:
1060:                scv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), name,
1061:                        desc);
1062:                scv.visitInsn(RETURN);
1063:                scv.visitMaxs(0, 0);
1064:            }
1065:
1066:            private void createInstrumentedSetter(int methodAccess,
1067:                    int fieldAccess, String name, String desc) {
1068:                try {
1069:                    Type t = Type.getType(desc);
1070:                    if (isRoot(methodAccess, name)) {
1071:                        createObjectSetter(methodAccess, fieldAccess, name,
1072:                                desc);
1073:                    }
1074:                    // if (((t.getSort() == Type.OBJECT) || (t.getSort() == Type.ARRAY)) && !isLiteral(desc)) {
1075:                    else if (((t.getSort() == Type.OBJECT) || (t.getSort() == Type.ARRAY))
1076:                            && !isPrimitive(t)) {
1077:                        createObjectSetter(methodAccess, fieldAccess, name,
1078:                                desc);
1079:                    } else {
1080:                        createLiteralSetter(methodAccess, fieldAccess, name,
1081:                                desc);
1082:                    }
1083:                } catch (RuntimeException e) {
1084:                    handleInstrumentationException(e);
1085:                } catch (Error e) {
1086:                    handleInstrumentationException(e);
1087:                    throw e;
1088:                }
1089:            }
1090:
1091:            private void createObjectSetter(int methodAccess, int fieldAccess,
1092:                    String name, String desc) {
1093:                try {
1094:                    if (isRoot(methodAccess, name)) {
1095:                        boolean isStaticRoot = Modifier.isStatic(methodAccess);
1096:                        if (instrumentationLogger.rootInsertion()) {
1097:                            instrumentationLogger.rootInserted(spec
1098:                                    .getClassNameDots(), name, desc,
1099:                                    isStaticRoot);
1100:                        }
1101:
1102:                        createRootSetter(methodAccess, name, desc, isStaticRoot);
1103:                    } else {
1104:                        createObjectFieldSetter(methodAccess, fieldAccess,
1105:                                name, desc);
1106:                    }
1107:                } catch (RuntimeException e) {
1108:                    handleInstrumentationException(e);
1109:                } catch (Error e) {
1110:                    handleInstrumentationException(e);
1111:                    throw e;
1112:                }
1113:            }
1114:
1115:            private boolean isRootDSOFinal(String name) {
1116:                return spec.getTransparencyClassSpec().isRootDSOFinal(
1117:                        spec.getFieldInfo(name));
1118:            }
1119:
1120:            private void createRootSetter(int methodAccess, String name,
1121:                    String desc, boolean isStatic) {
1122:                Type t = Type.getType(desc);
1123:                boolean isPrimitive = isPrimitive(t);
1124:                boolean isDSOFinal = isRootDSOFinal(name);
1125:
1126:                try {
1127:                    String sDesc = "(" + desc + ")V";
1128:                    String targetType = isPrimitive ? ByteCodeUtil
1129:                            .sortToWrapperName(t.getSort())
1130:                            : convertToCheckCastDesc(desc);
1131:                    MethodVisitor scv = cv.visitMethod(methodAccess,
1132:                            ByteCodeUtil.fieldSetterMethod(name), sDesc, null,
1133:                            null);
1134:
1135:                    Label tryStart = new Label();
1136:                    Label end = new Label();
1137:                    Label normalExit = new Label();
1138:                    Label finallyStart = new Label();
1139:                    Label exceptionHandler = new Label();
1140:
1141:                    final int rootInstance = isStatic ? 0 : 1;
1142:
1143:                    if (!isPrimitive) {
1144:                        scv.visitVarInsn(ALOAD, rootInstance);
1145:                        scv.visitJumpInsn(IFNULL, end); // Always ignore request to set roots to null
1146:                    }
1147:
1148:                    String rootName = rootNameFor(spec.getClassNameSlashes(),
1149:                            name);
1150:                    callTCBeginWithLockName(rootName, LockLevel.WRITE, scv);
1151:
1152:                    scv.visitLabel(tryStart);
1153:
1154:                    scv.visitLdcInsn(rootName);
1155:                    if (isPrimitive) {
1156:                        ByteCodeUtil.addTypeSpecificParameterLoad(scv, t,
1157:                                rootInstance);
1158:                    } else {
1159:                        scv.visitVarInsn(ALOAD, rootInstance);
1160:                    }
1161:                    if (isDSOFinal) {
1162:                        spec.getManagerHelper().callManagerMethod(
1163:                                "lookupOrCreateRoot", scv);
1164:                    } else {
1165:                        spec.getManagerHelper().callManagerMethod(
1166:                                "createOrReplaceRoot", scv);
1167:                    }
1168:
1169:                    int localVar = rootInstance + 1;
1170:                    scv.visitVarInsn(ASTORE, localVar);
1171:
1172:                    Label l0 = new Label();
1173:                    checkReturnObjectType(name, rootName, targetType, localVar,
1174:                            l0, scv);
1175:
1176:                    scv.visitLabel(l0);
1177:                    callPutFieldInsn(isStatic, t, localVar, name, desc, scv);
1178:                    scv.visitJumpInsn(GOTO, normalExit);
1179:
1180:                    scv.visitLabel(exceptionHandler);
1181:                    scv.visitVarInsn(ASTORE, 3);
1182:                    scv.visitJumpInsn(JSR, finallyStart);
1183:                    scv.visitVarInsn(ALOAD, 3);
1184:                    scv.visitInsn(ATHROW);
1185:
1186:                    scv.visitLabel(finallyStart);
1187:                    scv.visitVarInsn(ASTORE, 2);
1188:                    callTCCommitWithLockName(rootName, scv);
1189:                    scv.visitVarInsn(RET, 2);
1190:
1191:                    scv.visitLabel(normalExit);
1192:                    scv.visitJumpInsn(JSR, finallyStart);
1193:                    scv.visitLabel(end);
1194:                    scv.visitInsn(RETURN);
1195:                    scv.visitTryCatchBlock(tryStart, exceptionHandler,
1196:                            exceptionHandler, null);
1197:                    scv.visitMaxs(0, 0);
1198:                } catch (RuntimeException e) {
1199:                    handleInstrumentationException(e);
1200:                } catch (Error e) {
1201:                    handleInstrumentationException(e);
1202:                    throw e;
1203:                }
1204:            }
1205:
1206:            private void callGetFieldInsn(boolean isStatic, String name,
1207:                    String desc, MethodVisitor mv) {
1208:                int getInsn = isStatic ? GETSTATIC : GETFIELD;
1209:
1210:                if (!isStatic)
1211:                    ByteCodeUtil.pushThis(mv);
1212:                mv.visitFieldInsn(getInsn, spec.getClassNameSlashes(), name,
1213:                        desc);
1214:            }
1215:
1216:            private void callPutFieldInsn(boolean isStatic, Type targetType,
1217:                    int localVar, String name, String desc, MethodVisitor mv) {
1218:                int putInsn = isStatic ? PUTSTATIC : PUTFIELD;
1219:
1220:                if (!isStatic)
1221:                    ByteCodeUtil.pushThis(mv);
1222:                mv.visitVarInsn(ALOAD, localVar);
1223:
1224:                if (isPrimitive(targetType)) {
1225:                    mv.visitTypeInsn(CHECKCAST, ByteCodeUtil
1226:                            .sortToWrapperName(targetType.getSort()));
1227:                    mv.visitMethodInsn(INVOKEVIRTUAL, ByteCodeUtil
1228:                            .sortToWrapperName(targetType.getSort()),
1229:                            ByteCodeUtil.sortToPrimitiveMethodName(targetType
1230:                                    .getSort()), "()" + desc);
1231:                } else {
1232:                    mv.visitTypeInsn(CHECKCAST, convertToCheckCastDesc(desc));
1233:                }
1234:
1235:                mv.visitFieldInsn(putInsn, spec.getClassNameSlashes(), name,
1236:                        desc);
1237:            }
1238:
1239:            private void generateCodeForVolatileTransactionBegin(Label l1,
1240:                    Label l2, Label l3, Label l4, String fieldName,
1241:                    int lockLevel, MethodVisitor scv) {
1242:                scv.visitTryCatchBlock(l4, l1, l1, null);
1243:                scv.visitTryCatchBlock(l2, l3, l1, null);
1244:                scv.visitLabel(l4);
1245:                callVolatileBegin(fieldName, lockLevel, scv);
1246:            }
1247:
1248:            private void generateCodeForVolativeTransactionCommit(Label l1,
1249:                    Label l2, MethodVisitor scv, int newVar1, int newVar2,
1250:                    String fieldName) {
1251:                scv.visitJumpInsn(GOTO, l2);
1252:                scv.visitLabel(l1);
1253:                scv.visitVarInsn(ASTORE, newVar2);
1254:                Label l5 = new Label();
1255:                scv.visitJumpInsn(JSR, l5);
1256:                scv.visitVarInsn(ALOAD, newVar2);
1257:                scv.visitInsn(ATHROW);
1258:                scv.visitLabel(l5);
1259:                scv.visitVarInsn(ASTORE, newVar1);
1260:                callVolatileCommit(fieldName, scv);
1261:                scv.visitVarInsn(RET, newVar1);
1262:                scv.visitLabel(l2);
1263:                scv.visitJumpInsn(JSR, l5);
1264:            }
1265:
1266:            private void createObjectFieldSetter(int methodAccess,
1267:                    int fieldAccess, String name, String desc) {
1268:                try {
1269:                    boolean isVolatile = isVolatile(fieldAccess, name);
1270:                    Label l1 = new Label();
1271:                    Label l2 = new Label();
1272:                    Label l4 = new Label();
1273:
1274:                    // generates setter method
1275:                    String sDesc = "(" + desc + ")V";
1276:                    MethodVisitor scv = cv.visitMethod(methodAccess,
1277:                            ByteCodeUtil.fieldSetterMethod(name), sDesc, null,
1278:                            null);
1279:                    getManaged(scv);
1280:                    scv.visitInsn(DUP);
1281:                    scv.visitVarInsn(ASTORE, 2);
1282:                    Label l0 = new Label();
1283:                    scv.visitJumpInsn(IFNULL, l0);
1284:
1285:                    if (isVolatile) {
1286:                        generateCodeForVolatileTransactionBegin(l1, l2, l0, l4,
1287:                                spec.getClassNameDots() + "." + name,
1288:                                LockLevel.WRITE, scv);
1289:                    }
1290:
1291:                    scv.visitVarInsn(ALOAD, 2);
1292:                    scv.visitLdcInsn(spec.getClassNameDots());
1293:                    scv.visitLdcInsn(spec.getClassNameDots() + "." + name);
1294:                    scv.visitVarInsn(ALOAD, 1);
1295:                    scv.visitInsn(ICONST_M1);
1296:                    scv
1297:                            .visitMethodInsn(INVOKEINTERFACE,
1298:                                    "com/tc/object/TCObject",
1299:                                    "objectFieldChanged",
1300:                                    "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;I)V");
1301:
1302:                    if (isVolatile) {
1303:                        generateCodeForVolativeTransactionCommit(l1, l2, scv,
1304:                                3, 4, spec.getClassNameDots() + "." + name);
1305:                    }
1306:
1307:                    scv.visitLabel(l0);
1308:                    scv.visitVarInsn(ALOAD, 0);
1309:                    scv.visitVarInsn(ALOAD, 1);
1310:                    scv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(),
1311:                            name, desc);
1312:                    scv.visitInsn(RETURN);
1313:                    scv.visitMaxs(0, 0);
1314:                } catch (RuntimeException e) {
1315:                    handleInstrumentationException(e);
1316:                } catch (Error e) {
1317:                    handleInstrumentationException(e);
1318:                    throw e;
1319:                }
1320:            }
1321:
1322:            private void createLiteralSetter(int methodAccess, int fieldAccess,
1323:                    String name, String desc) {
1324:                try {
1325:                    // generates setter method
1326:                    boolean isVolatile = isVolatile(fieldAccess, name);
1327:
1328:                    Label l1 = new Label();
1329:                    Label l2 = new Label();
1330:                    Label l4 = new Label();
1331:
1332:                    String sDesc = "(" + desc + ")V";
1333:                    Type t = Type.getType(desc);
1334:
1335:                    MethodVisitor mv = cv.visitMethod(methodAccess,
1336:                            ByteCodeUtil.fieldSetterMethod(name), sDesc, null,
1337:                            null);
1338:                    getManaged(mv);
1339:                    mv.visitInsn(DUP);
1340:                    mv.visitVarInsn(ASTORE, 1 + t.getSize());
1341:                    Label l0 = new Label();
1342:                    mv.visitJumpInsn(IFNULL, l0);
1343:
1344:                    if (isVolatile) {
1345:                        generateCodeForVolatileTransactionBegin(l1, l2, l0, l4,
1346:                                spec.getClassNameDots() + "." + name,
1347:                                LockLevel.WRITE, mv);
1348:                    }
1349:
1350:                    mv.visitVarInsn(ALOAD, 1 + t.getSize());
1351:                    mv.visitLdcInsn(spec.getClassNameDots());
1352:                    mv.visitLdcInsn(spec.getClassNameDots() + "." + name);
1353:                    mv.visitVarInsn(t.getOpcode(ILOAD), 1);
1354:                    mv.visitInsn(ICONST_M1);
1355:                    String method = ByteCodeUtil.codeToName(desc)
1356:                            + "FieldChanged";
1357:                    mv.visitMethodInsn(INVOKEINTERFACE,
1358:                            "com/tc/object/TCObject", method,
1359:                            "(Ljava/lang/String;Ljava/lang/String;" + desc
1360:                                    + "I)V");
1361:
1362:                    if (isVolatile) {
1363:                        generateCodeForVolativeTransactionCommit(l1, l2, mv,
1364:                                2 + t.getSize(), 3 + t.getSize(), spec
1365:                                        .getClassNameDots()
1366:                                        + "." + name);
1367:                    }
1368:
1369:                    mv.visitLabel(l0);
1370:                    mv.visitVarInsn(ALOAD, 0);
1371:                    mv.visitVarInsn(t.getOpcode(ILOAD), 1);
1372:                    mv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(),
1373:                            name, desc);
1374:                    mv.visitInsn(RETURN);
1375:                    mv.visitMaxs(0, 0);
1376:                } catch (RuntimeException e) {
1377:                    handleInstrumentationException(e);
1378:                } catch (Error e) {
1379:                    handleInstrumentationException(e);
1380:                    throw e;
1381:                }
1382:            }
1383:
1384:            private void callTCMonitorExit(int callingMethodModifier,
1385:                    MethodVisitor c) {
1386:                Assert.eval("Can't call tc monitorenter from a static method.",
1387:                        !Modifier.isStatic(callingMethodModifier));
1388:                ByteCodeUtil.pushThis(c);
1389:                spec.getManagerHelper().callManagerMethod("monitorExit", c);
1390:            }
1391:
1392:            private void callTCMonitorEnter(int callingMethodModifier,
1393:                    LockDefinition def, MethodVisitor c) {
1394:                Assert.eval("Can't call tc monitorexit from a static method.",
1395:                        !Modifier.isStatic(callingMethodModifier));
1396:                ByteCodeUtil.pushThis(c);
1397:                c.visitLdcInsn(new Integer(def.getLockLevelAsInt()));
1398:                spec.getManagerHelper().callManagerMethod("monitorEnter", c);
1399:            }
1400:
1401:            private void addPrimitiveTypeZeroCompare(MethodVisitor mv,
1402:                    Type type, Label notZeroLabel) {
1403:                switch (type.getSort()) {
1404:                case Type.LONG:
1405:                    mv.visitInsn(LCONST_0);
1406:                    mv.visitInsn(LCMP);
1407:                    mv.visitJumpInsn(IFNE, notZeroLabel);
1408:                    break;
1409:                case Type.DOUBLE:
1410:                    mv.visitInsn(DCONST_0);
1411:                    mv.visitInsn(DCMPL);
1412:                    mv.visitJumpInsn(IFNE, notZeroLabel);
1413:                    break;
1414:                case Type.FLOAT:
1415:                    mv.visitInsn(FCONST_0);
1416:                    mv.visitInsn(FCMPL);
1417:                    mv.visitJumpInsn(IFNE, notZeroLabel);
1418:                    break;
1419:                default:
1420:                    mv.visitJumpInsn(IFNE, notZeroLabel);
1421:                }
1422:            }
1423:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.