Source Code Cross Referenced for TransparencyCodeAdapter.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) 


001:        /*
002:         * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003:         * notice. All rights reserved.
004:         */
005:        package com.tc.object.bytecode;
006:
007:        import com.tc.asm.Label;
008:        import com.tc.asm.MethodVisitor;
009:        import com.tc.asm.Opcodes;
010:        import com.tc.asm.Type;
011:        import com.tc.asm.commons.AdviceAdapter;
012:        import com.tc.aspectwerkz.reflect.ClassInfo;
013:        import com.tc.aspectwerkz.reflect.FieldInfo;
014:        import com.tc.aspectwerkz.reflect.MemberInfo;
015:        import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo;
016:        import com.tc.exception.TCInternalError;
017:        import com.tc.object.config.LockDefinition;
018:        import com.tc.object.config.TransparencyClassSpec;
019:        import com.tc.object.config.TransparencyCodeSpec;
020:        import com.tc.object.lockmanager.api.LockLevel;
021:
022:        import java.util.AbstractMap;
023:
024:        /**
025:         * @author steve
026:         */
027:        public class TransparencyCodeAdapter extends AdviceAdapter implements 
028:                Opcodes {
029:            private final boolean isAutolock;
030:            private final int autoLockType;
031:            private final ManagerHelper mgrHelper;
032:            private final InstrumentationSpec spec;
033:            private final MemberInfo memberInfo;
034:            private boolean isConstructor;
035:
036:            private final TransparencyCodeSpec codeSpec;
037:            private final Label labelZero = new Label();
038:
039:            private boolean visitInit = false;
040:            private boolean logicalInitVisited = false;
041:
042:            public TransparencyCodeAdapter(InstrumentationSpec spec,
043:                    boolean isAutolock, int autoLockType, MethodVisitor mv,
044:                    MemberInfo memberInfo, String originalName) {
045:                super (mv, memberInfo.getModifiers(), originalName, memberInfo
046:                        .getSignature());
047:                this .spec = spec;
048:                this .isAutolock = isAutolock;
049:                this .autoLockType = autoLockType;
050:                this .memberInfo = memberInfo;
051:
052:                this .mgrHelper = spec.getManagerHelper();
053:                this .codeSpec = spec.getTransparencyClassSpec().getCodeSpec(
054:                        memberInfo.getName(), //
055:                        memberInfo.getSignature(), isAutolock);
056:
057:                isConstructor = "<init>".equals(originalName);
058:                if (!isConstructor) {
059:                    visitInit = true;
060:                }
061:            }
062:
063:            private int[] storeStackValuesToLocalVariables(String methodInsnDesc) {
064:                Type[] types = Type.getArgumentTypes(methodInsnDesc);
065:                int[] localVariablesForMethodCall = new int[types.length];
066:                for (int i = 0; i < types.length; i++) {
067:                    localVariablesForMethodCall[i] = newLocal(types[i]);
068:                }
069:                for (int i = types.length - 1; i >= 0; i--) {
070:                    super .visitVarInsn(types[i].getOpcode(ISTORE),
071:                            localVariablesForMethodCall[i]);
072:                }
073:                return localVariablesForMethodCall;
074:            }
075:
076:            private void loadLocalVariables(String methodInsnDesc,
077:                    int[] localVariablesForMethodCall) {
078:                Type[] types = Type.getArgumentTypes(methodInsnDesc);
079:                for (int i = 0; i < types.length; i++) {
080:                    super .visitVarInsn(types[i].getOpcode(ILOAD),
081:                            localVariablesForMethodCall[i]);
082:                }
083:            }
084:
085:            public void visitMethodInsn(int opcode, String owner, String name,
086:                    String desc) {
087:                if (spec.hasDelegatedToLogicalClass() && isConstructor) {
088:                    logicalInitVisitMethodInsn(opcode, owner, name, desc);
089:                } else {
090:                    basicVisitMethodInsn(opcode, owner, name, desc);
091:                }
092:            }
093:
094:            private void logicalInitVisitMethodInsn(int opcode, String owner,
095:                    String name, String desc) {
096:                String super ClassNameSlashes = spec.getSuperClassNameSlashes();
097:                if (!logicalInitVisited && INVOKESPECIAL == opcode
098:                        && owner.equals(super ClassNameSlashes)
099:                        && "<init>".equals(name)) {
100:                    logicalInitVisited = true;
101:                    int[] localVariablesForMethodCall = storeStackValuesToLocalVariables(desc);
102:                    loadLocalVariables(desc, localVariablesForMethodCall);
103:                    super .visitMethodInsn(opcode, owner, name, desc);
104:                    super .visitVarInsn(ALOAD, 0);
105:                    super .visitTypeInsn(NEW, spec.getSuperClassNameSlashes());
106:                    super .visitInsn(DUP);
107:                    loadLocalVariables(desc, localVariablesForMethodCall);
108:
109:                    String delegateFieldName = ClassAdapterBase
110:                            .getDelegateFieldName(super ClassNameSlashes);
111:                    super .visitMethodInsn(INVOKESPECIAL, super ClassNameSlashes,
112:                            "<init>", desc);
113:                    super .visitMethodInsn(INVOKESPECIAL, spec
114:                            .getClassNameSlashes(), ByteCodeUtil
115:                            .fieldSetterMethod(delegateFieldName), "(L"
116:                            + super ClassNameSlashes + ";)V");
117:
118:                } else {
119:                    basicVisitMethodInsn(opcode, owner, name, desc);
120:                }
121:            }
122:
123:            private void basicVisitMethodInsn(int opcode, String classname,
124:                    String theMethodName, String desc) {
125:                if (handleSubclassOfLogicalClassMethodInsn(opcode, classname,
126:                        theMethodName, desc)) {
127:                    return;
128:                }
129:                if (codeSpec.isArraycopyInstrumentationReq(classname,
130:                        theMethodName)) {
131:                    rewriteArraycopy();
132:                } else if (classname.equals("java/lang/Object")) {
133:                    handleJavaLangObjectMethodCall(opcode, classname,
134:                            theMethodName, desc);
135:                } else {
136:                    super .visitMethodInsn(opcode, classname, theMethodName,
137:                            desc);
138:                }
139:            }
140:
141:            private boolean handleSubclassOfLogicalClassMethodInsn(int opcode,
142:                    String classname, String theMethodName, String desc) {
143:                if (!spec.hasDelegatedToLogicalClass()) {
144:                    return false;
145:                }
146:                String logicalExtendingClassName = spec
147:                        .getSuperClassNameSlashes();
148:                if (INVOKESPECIAL == opcode
149:                        && !spec.getClassNameSlashes().equals(classname)
150:                        && !"<init>".equals(theMethodName)) {
151:                    spec.shouldProceedInstrumentation(
152:                            memberInfo.getModifiers(), theMethodName, desc);
153:                    int[] localVariablesForMethodCall = storeStackValuesToLocalVariables(desc);
154:                    super 
155:                            .visitMethodInsn(
156:                                    INVOKESPECIAL,
157:                                    spec.getClassNameSlashes(),
158:                                    ByteCodeUtil
159:                                            .fieldGetterMethod(ClassAdapterBase
160:                                                    .getDelegateFieldName(logicalExtendingClassName)),
161:                                    "()L" + logicalExtendingClassName + ";");
162:                    loadLocalVariables(desc, localVariablesForMethodCall);
163:                    super .visitMethodInsn(INVOKEVIRTUAL,
164:                            logicalExtendingClassName, theMethodName, desc);
165:                    return true;
166:                }
167:                return false;
168:            }
169:
170:            private TransparencyClassSpec getTransparencyClassSpec() {
171:                return spec.getTransparencyClassSpec();
172:            }
173:
174:            private void rewriteArraycopy() {
175:                callArrayManagerMethod("arraycopy",
176:                        "(Ljava/lang/Object;ILjava/lang/Object;II)V");
177:            }
178:
179:            private void handleJavaLangObjectMethodCall(int opcode,
180:                    String classname, String theMethodName, String desc) {
181:                if (handleJavaLangObjectWaitNotifyCalls(opcode, classname,
182:                        theMethodName, desc)) {
183:                    return;
184:                } else if (handleJavaLangObjectCloneCall(opcode, classname,
185:                        theMethodName, desc)) {
186:                    return;
187:                } else {
188:                    super .visitMethodInsn(opcode, classname, theMethodName,
189:                            desc);
190:                }
191:            }
192:
193:            /**
194:             * The assumption here is that the compiler wouldn't call invokevirtual on a classname other than java.lang.Object
195:             * when there is no implementation of clone() defined in that classes' hierarchy. If it does, it a bug in the compiler
196:             * ;-) This adaption is needed for both PORTABLE and ADAPTABLE classes as we can have instance where Logical subclass
197:             * of ADAPTABLE class calls clone() to make a copy of itself.
198:             *
199:             * The resolveLock needs to be held for the duration of the clone() call if the reference is to a shared object
200:             *
201:             * <pre>
202:             * Object refToBeCloned;
203:             * Object rv;
204:             *
205:             * TCObject tco = (refToBeCloned instanceof Manageable) ? ((Manageable) refToBeCloned).__tc_managed() : null;
206:             * if (tco != null) {
207:             *   synchronized (tco.getResolveLock()) {
208:             *     tco.resolveAllReferences();
209:             *     rv = Util.fixTCObjectReferenceOfClonedObject(refToBeCloned, refToBeCloned.clone());
210:             *   }
211:             * } else {
212:             *   rv = refToBeCloned.clone();
213:             * }
214:             * </pre>
215:             *
216:             * @see AbstractMap and HashMap
217:             */
218:            private boolean handleJavaLangObjectCloneCall(int opcode,
219:                    String classname, String theMethodName, String desc) {
220:                if ("clone".equals(theMethodName)
221:                        && "()Ljava/lang/Object;".equals(desc)) {
222:
223:                    Type objectType = Type.getObjectType("java/lang/Object");
224:
225:                    int refToBeCloned = newLocal(objectType);
226:                    int ref1 = newLocal(objectType);
227:                    int ref2 = newLocal(objectType);
228:                    int ref3 = newLocal(objectType);
229:
230:                    super .visitVarInsn(ASTORE, refToBeCloned);
231:                    Label l0 = new Label();
232:                    Label l1 = new Label();
233:                    Label l2 = new Label();
234:                    super .visitTryCatchBlock(l0, l1, l2, null);
235:                    Label l3 = new Label();
236:                    super .visitTryCatchBlock(l2, l3, l2, null);
237:                    super .visitVarInsn(ALOAD, refToBeCloned);
238:                    super .visitTypeInsn(INSTANCEOF,
239:                            "com/tc/object/bytecode/Manageable");
240:                    Label l5 = new Label();
241:                    super .visitJumpInsn(IFEQ, l5);
242:                    super .visitVarInsn(ALOAD, refToBeCloned);
243:                    super .visitTypeInsn(CHECKCAST,
244:                            "com/tc/object/bytecode/Manageable");
245:                    super .visitMethodInsn(INVOKEINTERFACE,
246:                            "com/tc/object/bytecode/Manageable",
247:                            "__tc_managed", "()Lcom/tc/object/TCObject;");
248:                    Label l6 = new Label();
249:                    super .visitJumpInsn(GOTO, l6);
250:                    super .visitLabel(l5);
251:                    super .visitInsn(ACONST_NULL);
252:                    super .visitLabel(l6);
253:                    super .visitVarInsn(ASTORE, ref2);
254:                    super .visitVarInsn(ALOAD, ref2);
255:                    Label l8 = new Label();
256:                    super .visitJumpInsn(IFNULL, l8);
257:                    super .visitVarInsn(ALOAD, ref2);
258:                    super .visitMethodInsn(INVOKEINTERFACE,
259:                            "com/tc/object/TCObject", "getResolveLock",
260:                            "()Ljava/lang/Object;");
261:                    super .visitInsn(DUP);
262:                    super .visitVarInsn(ASTORE, ref3);
263:                    super .visitInsn(MONITORENTER);
264:                    super .visitLabel(l0);
265:                    super .visitVarInsn(ALOAD, ref2);
266:                    super .visitMethodInsn(INVOKEINTERFACE,
267:                            "com/tc/object/TCObject", "resolveAllReferences",
268:                            "()V");
269:                    super .visitVarInsn(ALOAD, refToBeCloned);
270:                    super .visitVarInsn(ALOAD, refToBeCloned);
271:                    super .visitMethodInsn(opcode, classname, theMethodName,
272:                            desc);
273:                    super 
274:                            .visitMethodInsn(INVOKESTATIC,
275:                                    "com/tc/object/bytecode/hook/impl/Util",
276:                                    "fixTCObjectReferenceOfClonedObject",
277:                                    "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
278:                    super .visitVarInsn(ASTORE, ref1);
279:                    super .visitVarInsn(ALOAD, ref3);
280:                    super .visitInsn(MONITOREXIT);
281:                    super .visitLabel(l1);
282:                    Label l12 = new Label();
283:                    super .visitJumpInsn(GOTO, l12);
284:                    super .visitLabel(l2);
285:                    super .visitVarInsn(ALOAD, ref3);
286:                    super .visitInsn(MONITOREXIT);
287:                    super .visitLabel(l3);
288:                    super .visitInsn(ATHROW);
289:                    super .visitLabel(l8);
290:                    super .visitVarInsn(ALOAD, refToBeCloned);
291:                    super .visitMethodInsn(opcode, classname, theMethodName,
292:                            desc);
293:                    super .visitVarInsn(ASTORE, ref1);
294:                    super .visitLabel(l12);
295:                    super .visitVarInsn(ALOAD, ref1);
296:                    return true;
297:                }
298:                return false;
299:            }
300:
301:            private boolean handleJavaLangObjectWaitNotifyCalls(int opcode,
302:                    String classname, String theMethodName, String desc) {
303:                if (spec.isLogical()
304:                        || !codeSpec.isWaitNotifyInstrumentationReq()) {
305:                    return false;
306:                }
307:
308:                Type[] args = Type.getArgumentTypes(desc);
309:
310:                if (theMethodName.equals("notify")
311:                        || theMethodName.equals("notifyAll")) {
312:                    if (args.length == 0) {
313:                        if (theMethodName.endsWith("All")) {
314:                            mgrHelper
315:                                    .callManagerMethod("objectNotifyAll", this );
316:                        } else {
317:                            mgrHelper.callManagerMethod("objectNotify", this );
318:                        }
319:                        return true;
320:                    }
321:                    throw new TCInternalError(
322:                            "Unexpected java.lang.Object method signature: "
323:                                    + theMethodName + " + " + desc);
324:                } else if (theMethodName.equals("wait")) {
325:
326:                    switch (args.length) {
327:                    case 0: {
328:                        mgrHelper.callManagerMethod("objectWait0", this );
329:                        return true;
330:                    }
331:                    case 1: {
332:                        if (args[0].equals(Type.LONG_TYPE)) {
333:                            mgrHelper.callManagerMethod("objectWait1", this );
334:                            return true;
335:                        }
336:                        throw new TCInternalError(
337:                                "Unexpected java.lang.Object method signature: "
338:                                        + theMethodName + " + " + desc);
339:                    }
340:                    case 2: {
341:                        if ((args[0].equals(Type.LONG_TYPE))
342:                                && (args[1].equals(Type.INT_TYPE))) {
343:                            mgrHelper.callManagerMethod("objectWait2", this );
344:                            return true;
345:                        }
346:                        throw new TCInternalError(
347:                                "Unexpected java.lang.Object method signature: "
348:                                        + theMethodName + " + " + desc);
349:                    }
350:                    default: {
351:                        throw new TCInternalError(
352:                                "Unexpected java.lang.Object method signature: "
353:                                        + theMethodName + " + " + desc);
354:                    }
355:                    }
356:                } else { // neither wait(...) nor notify[All]()
357:                    return false;
358:                }
359:
360:                // should be unreachable
361:            }
362:
363:            private void callTCBeginWithLocks(MethodVisitor c) {
364:                c.visitLabel(new Label());
365:                LockDefinition[] defs = getTransparencyClassSpec()
366:                        .lockDefinitionsFor(memberInfo);
367:                for (int i = 0; i < defs.length; i++) {
368:                    if (!defs[i].isAutolock()) {
369:                        callTCBeginWithLock(defs[i], c);
370:                    }
371:                }
372:            }
373:
374:            private void callTCBeginWithLock(LockDefinition lock,
375:                    MethodVisitor c) {
376:                c.visitLdcInsn(ByteCodeUtil.generateNamedLockName(lock
377:                        .getLockName()));
378:                c.visitLdcInsn(new Integer(lock.getLockLevelAsInt()));
379:                mgrHelper.callManagerMethod("beginLock", c);
380:            }
381:
382:            private void callTCCommit(MethodVisitor c) {
383:                LockDefinition[] locks = getTransparencyClassSpec()
384:                        .lockDefinitionsFor(memberInfo);
385:                for (int i = 0; i < locks.length; i++) {
386:                    if (!locks[i].isAutolock()) {
387:                        c.visitLdcInsn(ByteCodeUtil
388:                                .generateNamedLockName(locks[i].getLockName()));
389:                        mgrHelper.callManagerMethod("commitLock", c);
390:                    }
391:                }
392:            }
393:
394:            private void visitInsnForReadLock(int opCode) {
395:                switch (opCode) {
396:                case MONITORENTER:
397:                    super .visitInsn(DUP);
398:                    super .visitMethodInsn(INVOKESTATIC,
399:                            "com/tc/object/bytecode/ManagerUtil",
400:                            "isDsoMonitored", "(Ljava/lang/Object;)Z");
401:                    Label l1 = new Label();
402:                    super .visitJumpInsn(IFEQ, l1);
403:                    super .visitLdcInsn(new Integer(autoLockType));
404:                    mgrHelper.callManagerMethod("monitorEnter", this );
405:                    Label l2 = new Label();
406:                    super .visitJumpInsn(GOTO, l2);
407:                    super .visitLabel(l1);
408:                    super .visitInsn(opCode);
409:                    super .visitLabel(l2);
410:                    return;
411:                case MONITOREXIT:
412:                    super .visitInsn(DUP);
413:                    super .visitMethodInsn(INVOKESTATIC,
414:                            "com/tc/object/bytecode/ManagerUtil",
415:                            "isDsoMonitorEntered", "(Ljava/lang/Object;)Z");
416:                    Label l3 = new Label();
417:                    super .visitJumpInsn(IFEQ, l3);
418:                    mgrHelper.callManagerMethod("monitorExit", this );
419:                    Label l4 = new Label();
420:                    super .visitJumpInsn(GOTO, l4);
421:                    super .visitLabel(l3);
422:                    super .visitInsn(opCode);
423:                    super .visitLabel(l4);
424:                    return;
425:                }
426:            }
427:
428:            public void visitInsn(int opCode) {
429:                if (isMonitorInstrumentationReq(opCode)) {
430:                    switch (opCode) {
431:                    case MONITORENTER:
432:                        if (this .isAutolock) {
433:                            if (autoLockType == LockLevel.READ) {
434:                                visitInsnForReadLock(opCode);
435:                                return;
436:                            }
437:                            super .visitInsn(DUP);
438:                            super .visitLdcInsn(new Integer(autoLockType));
439:                            mgrHelper.callManagerMethod("monitorEnter", this );
440:                            super .visitInsn(opCode);
441:                        } else {
442:                            super .visitInsn(opCode);
443:                        }
444:                        return;
445:                    case MONITOREXIT:
446:                        if (this .isAutolock) {
447:                            if (autoLockType == LockLevel.READ) {
448:                                visitInsnForReadLock(opCode);
449:                                return;
450:                            }
451:                            super .visitInsn(DUP);
452:                            super .visitInsn(opCode);
453:                            mgrHelper.callManagerMethod("monitorExit", this );
454:                        } else {
455:                            super .visitInsn(opCode);
456:                        }
457:                        return;
458:                    }
459:                }
460:                if (isArrayOperatorInstrumentationReq(opCode)) {
461:                    switch (opCode) {
462:                    case AALOAD:
463:                        Label end = new Label();
464:                        Label notManaged = new Label();
465:                        Label noIndexException = new Label();
466:                        super .visitInsn(DUP2);
467:                        super .visitInsn(POP);
468:                        callArrayManagerMethod("getObject",
469:                                "(Ljava/lang/Object;)Lcom/tc/object/TCObject;");
470:                        super .visitInsn(DUP);
471:                        super .visitJumpInsn(IFNULL, notManaged);
472:                        super .visitInsn(DUP2);
473:                        super .visitInsn(SWAP);
474:                        super 
475:                                .visitMethodInsn(INVOKEINTERFACE,
476:                                        "com/tc/object/TCObject",
477:                                        "checkArrayIndex",
478:                                        "(I)Ljava/lang/ArrayIndexOutOfBoundsException;");
479:                        super .visitInsn(DUP);
480:                        super .visitJumpInsn(IFNULL, noIndexException);
481:                        super .visitInsn(SWAP);
482:                        super .visitInsn(POP);
483:                        super .visitInsn(SWAP);
484:                        super .visitInsn(POP);
485:                        super .visitInsn(SWAP);
486:                        super .visitInsn(POP);
487:                        super .visitInsn(ATHROW);
488:                        super .visitLabel(noIndexException);
489:                        super .visitInsn(POP);
490:                        super .visitInsn(DUP_X2);
491:                        super .visitInsn(DUP);
492:                        super .visitMethodInsn(INVOKEINTERFACE,
493:                                "com/tc/object/TCObject", "getResolveLock",
494:                                "()Ljava/lang/Object;");
495:                        super .visitInsn(MONITORENTER);
496:                        super .visitInsn(DUP2);
497:                        super .visitInsn(SWAP);
498:                        super .visitMethodInsn(INVOKEINTERFACE,
499:                                "com/tc/object/TCObject",
500:                                "resolveArrayReference", "(I)V");
501:                        super .visitInsn(POP);
502:                        super .visitInsn(opCode);
503:                        super .visitInsn(SWAP);
504:                        super .visitMethodInsn(INVOKEINTERFACE,
505:                                "com/tc/object/TCObject", "getResolveLock",
506:                                "()Ljava/lang/Object;");
507:                        super .visitInsn(MONITOREXIT);
508:                        super .visitJumpInsn(GOTO, end);
509:                        super .visitLabel(notManaged);
510:                        super .visitInsn(POP);
511:                        super .visitInsn(opCode);
512:                        super .visitLabel(end);
513:                        return;
514:                    case AASTORE:
515:                        callArrayManagerMethod("objectArrayChanged",
516:                                "([Ljava/lang/Object;ILjava/lang/Object;)V");
517:                        return;
518:                    case LASTORE:
519:                        callArrayManagerMethod("longArrayChanged", "([JIJ)V");
520:                        return;
521:                    case SASTORE:
522:                        callArrayManagerMethod("shortArrayChanged", "([SIS)V");
523:                        return;
524:                    case IASTORE:
525:                        callArrayManagerMethod("intArrayChanged", "([III)V");
526:                        return;
527:                    case DASTORE:
528:                        callArrayManagerMethod("doubleArrayChanged", "([DID)V");
529:                        return;
530:                    case FASTORE:
531:                        callArrayManagerMethod("floatArrayChanged", "([FIF)V");
532:                        return;
533:                    case BASTORE:
534:                        callArrayManagerMethod("byteOrBooleanArrayChanged",
535:                                "(Ljava/lang/Object;IB)V");
536:                        return;
537:                    case CASTORE:
538:                        callArrayManagerMethod("charArrayChanged", "([CIC)V");
539:                        return;
540:                    }
541:                }
542:                super .visitInsn(opCode);
543:            }
544:
545:            private boolean isArrayOperatorInstrumentationReq(int opCode) {
546:                return ((opCode == AALOAD || opCode == AASTORE
547:                        || opCode == LASTORE || opCode == SASTORE
548:                        || opCode == IASTORE || opCode == DASTORE
549:                        || opCode == FASTORE || opCode == BASTORE || opCode == CASTORE) && codeSpec
550:                        .isArrayOperatorInstrumentationReq());
551:            }
552:
553:            private boolean isMonitorInstrumentationReq(int opCode) {
554:                return ((opCode == MONITORENTER || opCode == MONITOREXIT) && codeSpec
555:                        .isMonitorInstrumentationReq());
556:            }
557:
558:            private void callArrayManagerMethod(String name, String desc) {
559:                super .visitMethodInsn(INVOKESTATIC, ManagerUtil.CLASS, name,
560:                        desc);
561:            }
562:
563:            public void visitMaxs(int stack, int vars) {
564:                super .visitMaxs(stack, vars + 1);
565:            }
566:
567:            public void visitFieldInsn(final int opcode,
568:                    final String classname, final String fieldName,
569:                    final String desc) {
570:                spec.shouldProceedInstrumentation(fieldName, desc);
571:
572:                if (!spec.needInstrumentFieldInsn() || !visitInit
573:                        || !codeSpec.isFieldInstrumentationReq(fieldName)) {
574:                    super .visitFieldInsn(opcode, classname, fieldName, desc);
575:                    return;
576:                }
577:
578:                if (spec.isPhysical()) {
579:                    // if (opcode == GETFIELD && (isRoot(classname, fieldName) || !isPrimitive(Type.getType(desc)))) {
580:                    if (opcode == GETFIELD) {
581:                        visitGetFieldInsn(classname, fieldName, desc);
582:                        return;
583:                    } else if (opcode == PUTFIELD) {
584:                        visitSetFieldInsn(classname, fieldName, desc);
585:                        return;
586:                    } else if (opcode == PUTSTATIC
587:                            && isRoot(classname, fieldName)) {
588:                        String sDesc = "(" + desc + ")V";
589:                        visitMethodInsn(INVOKESTATIC, classname, ByteCodeUtil
590:                                .fieldSetterMethod(fieldName), sDesc);
591:                        return;
592:                    } else if (opcode == GETSTATIC
593:                            && isRoot(classname, fieldName)) {
594:                        String gDesc = "()" + desc;
595:                        visitMethodInsn(INVOKESTATIC, classname, ByteCodeUtil
596:                                .fieldGetterMethod(fieldName), gDesc);
597:                        return;
598:                    }
599:                    super .visitFieldInsn(opcode, classname, fieldName, desc);
600:                } else {
601:                    super .visitFieldInsn(opcode, classname, fieldName, desc);
602:                }
603:            }
604:
605:            private void visitSetFieldInsn(String classname, String fieldName,
606:                    String desc) {
607:                boolean inClassHierarchy = spec.isInClassHierarchy(classname);
608:                if ((spec.isClassPortable() && inClassHierarchy)
609:                        || isRoot(classname, fieldName)) {
610:                    // If the field is a root, we assume that the class is instrumented automatically.
611:                    // If it is not then bad things are gonna happen anyway.
612:                    visitUncheckedSetFieldInsn(classname, fieldName, desc);
613:                } else if (spec.isClassAdaptable() && inClassHierarchy) {
614:                    visitSetFieldInsnOriginal(classname, fieldName, desc);
615:                } else {
616:                    visitCheckedSetFieldInsn(classname, fieldName, desc);
617:                }
618:            }
619:
620:            private void visitSetFieldInsnOriginal(String classname,
621:                    String fieldName, String desc) {
622:                // System.err.println("Original :: My class : " + spec.getClassNameSlashes() + " set on : " + classname + " field :
623:                // " + fieldName);
624:                super .visitFieldInsn(PUTFIELD, classname, fieldName, desc);
625:            }
626:
627:            private void visitUncheckedSetFieldInsn(String classname,
628:                    String fieldName, String desc) {
629:                // System.err.println("Unchecked :: My class : " + spec.getClassNameSlashes() + " set on : " + classname + " field :
630:                // " + fieldName);
631:                String sDesc = "(" + desc + ")V";
632:                visitMethodInsn(INVOKEVIRTUAL, classname, ByteCodeUtil
633:                        .fieldSetterMethod(fieldName), sDesc);
634:            }
635:
636:            /**
637:             * This method assumes that we dont have anyinfo on the class that we are setting the field to. so we take the
638:             * conservative approach.
639:             */
640:            private void visitCheckedSetFieldInsn(String classname,
641:                    String fieldName, String desc) {
642:                // System.err.println("Checked :: My class : " + spec.getClassNameSlashes() + " set on : " + classname + " field : "
643:                // + fieldName);
644:                Type fieldType = Type.getType(desc);
645:                Type reference = Type.getType("Ljava/lang/Object;");
646:                String sDesc = "(" + desc + ")V";
647:
648:                swap(reference, fieldType);
649:                super .visitInsn(DUP);
650:                Label l1 = new Label();
651:                super .visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
652:                        "getClass", "()Ljava/lang/Class;");
653:                mgrHelper.callManagerMethod("isPhysicallyInstrumented", this );
654:                super .visitJumpInsn(IFEQ, l1);
655:                swap(fieldType, reference);
656:                visitMethodInsn(INVOKEVIRTUAL, classname, ByteCodeUtil
657:                        .fieldSetterMethod(fieldName), sDesc);
658:                Label l2 = new Label();
659:                super .visitJumpInsn(GOTO, l2);
660:                super .visitLabel(l1);
661:                swap(fieldType, reference);
662:                super .visitFieldInsn(PUTFIELD, classname, fieldName, desc);
663:                super .visitLabel(l2);
664:            }
665:
666:            private void visitGetFieldInsn(String classname, String fieldName,
667:                    String desc) {
668:                boolean inClassHierarchy = spec.isInClassHierarchy(classname);
669:                if ((spec.isClassPortable() && inClassHierarchy)
670:                        || isRoot(classname, fieldName)) {
671:                    // If the field is a root, we assume that the class is instrumented automatically.
672:                    // If it is not then bad things are gonna happen anyway.
673:                    visitUncheckedGetFieldInsn(classname, fieldName, desc);
674:                } else if (spec.isClassAdaptable() && inClassHierarchy) {
675:                    visitGetFieldInsnOriginal(classname, fieldName, desc);
676:                } else {
677:                    visitCheckedGetFieldInsn(classname, fieldName, desc);
678:                }
679:            }
680:
681:            private void visitGetFieldInsnOriginal(String classname,
682:                    String fieldName, String desc) {
683:                // System.err.println("Original :: My class : " + spec.getClassNameSlashes() + " get on : " + classname + " field :
684:                // " + fieldName);
685:                super .visitFieldInsn(GETFIELD, classname, fieldName, desc);
686:            }
687:
688:            private void visitUncheckedGetFieldInsn(String classname,
689:                    String fieldName, String desc) {
690:                // System.err.println("Unchecked :: My class: " + spec.getClassNameSlashes() + " get on : " + classname + " field :
691:                // " + fieldName);
692:                String gDesc = "()" + desc;
693:                visitMethodInsn(INVOKEVIRTUAL, classname, ByteCodeUtil
694:                        .fieldGetterMethod(fieldName), gDesc);
695:            }
696:
697:            /**
698:             * This method assumes that we dont have anyinfo on the class that we are setting the field to. so we take the
699:             * conservative approach.
700:             */
701:            private void visitCheckedGetFieldInsn(String classname,
702:                    String fieldName, String desc) {
703:                String gDesc = "()" + desc;
704:                super .visitInsn(DUP);
705:                Label l1 = new Label();
706:                super .visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
707:                        "getClass", "()Ljava/lang/Class;");
708:                mgrHelper.callManagerMethod("isPhysicallyInstrumented", this );
709:                super .visitJumpInsn(IFEQ, l1);
710:                visitMethodInsn(INVOKEVIRTUAL, classname, ByteCodeUtil
711:                        .fieldGetterMethod(fieldName), gDesc);
712:                Label l2 = new Label();
713:                super .visitJumpInsn(GOTO, l2);
714:                super .visitLabel(l1);
715:                super .visitFieldInsn(GETFIELD, classname, fieldName, desc);
716:                super .visitLabel(l2);
717:            }
718:
719:            private boolean isRoot(String classname, String fieldName) {
720:                ClassInfo classInfo = AsmClassInfo.getClassInfo(classname
721:                        .replace('/', '.'), spec.getCaller());
722:                FieldInfo[] fields = classInfo.getFields();
723:                for (int i = 0; i < fields.length; i++) {
724:                    FieldInfo fieldInfo = fields[i];
725:
726:                    if (fieldName.equals(fieldInfo.getName())) {
727:                        if (getTransparencyClassSpec().isRoot(fieldInfo)) {
728:                            return true;
729:                        }
730:                    }
731:                }
732:
733:                return false;
734:            }
735:
736:            protected void onMethodEnter() {
737:                if (isConstructor) {
738:                    visitInit = true;
739:                    if (getTransparencyClassSpec().isLockMethod(memberInfo)) {
740:                        callTCBeginWithLocks(this );
741:                        super .visitLabel(labelZero);
742:                    }
743:                }
744:            }
745:
746:            protected void onMethodExit(int opcode) {
747:                if (isConstructor
748:                        && getTransparencyClassSpec().isLockMethod(memberInfo)) {
749:
750:                    if (opcode == RETURN) {
751:                        callTCCommit(this );
752:                    } else if (opcode == ATHROW) {
753:                        // nothing special to do here, exception handler for method will do the commit
754:                    } else {
755:                        // <init> should not be returning with any other opcodes
756:                        throw new AssertionError(
757:                                "unexpected exit instruction: " + opcode);
758:                    }
759:                }
760:            }
761:
762:            public void visitEnd() {
763:                if (isConstructor
764:                        && getTransparencyClassSpec().isLockMethod(memberInfo)) {
765:                    Label labelEnd = new Label();
766:                    super .visitLabel(labelEnd);
767:                    super .visitTryCatchBlock(labelZero, labelEnd, labelEnd,
768:                            null);
769:                    int localVar = newLocal(Type
770:                            .getObjectType("java/lang/Object"));
771:                    super.visitVarInsn(ASTORE, localVar);
772:                    callTCCommit(mv);
773:                    super.visitVarInsn(ALOAD, localVar);
774:                    mv.visitInsn(ATHROW);
775:                }
776:
777:                super.visitEnd();
778:            }
779:
780:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.