001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.bytecode;
005:
006: import com.tc.asm.ClassVisitor;
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.aspectwerkz.reflect.MemberInfo;
012: import com.tc.object.config.MethodSpec;
013: import com.tc.object.logging.InstrumentationLogger;
014: import com.tcclient.util.MapEntrySetWrapper;
015: import com.tcclient.util.SortedViewSetWrapper;
016:
017: import java.lang.reflect.Modifier;
018:
019: /**
020: * Used to create wrappers for logical methods
021: */
022: public class LogicalMethodAdapter implements MethodAdapter, Opcodes {
023: private String ownerSlashes;
024: private String methodName;
025: private String originalMethodName;
026: private ManagerHelper managerHelper;
027: private String description;
028: private int access;
029: private String[] exceptions;
030: private String signature;
031: private int instrumentationType;
032: private int wrapperAccess;
033:
034: public LogicalMethodAdapter() {
035: // When using this as a Method creator it doesn't need any of that stuff. yuck :-)
036: }
037:
038: public LogicalMethodAdapter(String methodName,
039: int instrumentationType) {
040: this .methodName = methodName;
041: this .instrumentationType = instrumentationType;
042: }
043:
044: public void initialize(ManagerHelper aManagerHelper, int anAccess,
045: String aClassName, String aMethodName,
046: String aOriginalMethodName, String aDescription,
047: String sig, String[] anExceptions,
048: InstrumentationLogger logger, MemberInfo info) {
049: this .managerHelper = aManagerHelper;
050: this .ownerSlashes = aClassName.replace('.', '/');
051: this .methodName = aMethodName;
052: this .originalMethodName = aOriginalMethodName;
053: this .description = aDescription;
054: this .wrapperAccess = anAccess & (~Modifier.SYNCHRONIZED); // wrapper method should have synch removed
055: this .access = anAccess;
056: this .exceptions = anExceptions;
057: this .signature = sig;
058: }
059:
060: public MethodVisitor adapt(ClassVisitor classVisitor) {
061: createWrapperMethod(classVisitor);
062: return classVisitor.visitMethod(access, getNewName(),
063: description, signature, exceptions);
064: }
065:
066: public boolean doesOriginalNeedAdapting() {
067: return true;
068: }
069:
070: protected String getNewName() {
071: return ByteCodeUtil.TC_METHOD_PREFIX + methodName;
072: }
073:
074: protected void createWrapperMethod(ClassVisitor classVisitor) {
075: switch (instrumentationType) {
076: case MethodSpec.ALWAYS_LOG:
077: createAlwaysLogWrapperMethod(classVisitor, true);
078: break;
079: case MethodSpec.HASHMAP_REMOVE_LOG:
080: createHashMapRemoveWrapperMethod(classVisitor, true);
081: break;
082: case MethodSpec.HASHTABLE_REMOVE_LOG:
083: createHashMapRemoveWrapperMethod(classVisitor, false);
084: break;
085: case MethodSpec.THASH_REMOVE_AT_LOG:
086: createTHashRemoveAtWrapperMethod(classVisitor);
087: break;
088: case MethodSpec.HASHMAP_PUT_LOG:
089: createHashPutWrapperMethod(classVisitor, true);
090: break;
091: case MethodSpec.HASHTABLE_PUT_LOG:
092: createHashPutWrapperMethod(classVisitor, false);
093: break;
094: case MethodSpec.HASHTABLE_CLEAR_LOG:
095: createAlwaysLogWrapperMethod(classVisitor, false);
096: break;
097: case MethodSpec.THASHSET_ADD_LOG:
098: createTHashSetAddWrapperMethod(classVisitor);
099: break;
100: case MethodSpec.THASHMAP_PUT_LOG:
101: createTHashMapPutWrapperMethod(classVisitor);
102: break;
103: case MethodSpec.IF_TRUE_LOG:
104: createIfTrueLogWrapperMethod(classVisitor);
105: break;
106: case MethodSpec.SET_ITERATOR_WRAPPER_LOG:
107: createSetIteratorWrapper(classVisitor);
108: break;
109: case MethodSpec.ENTRY_SET_WRAPPER_LOG:
110: createEntrySetWrapper(classVisitor);
111: break;
112: case MethodSpec.KEY_SET_WRAPPER_LOG:
113: createKeySetWrapper(classVisitor);
114: break;
115: case MethodSpec.VALUES_WRAPPER_LOG:
116: createValuesWrapper(classVisitor);
117: break;
118: case MethodSpec.SORTED_SET_VIEW_WRAPPER_LOG:
119: createSortedViewSetWrapper(classVisitor);
120: break;
121: default:
122: throw new AssertionError("illegal instrumentationType:"
123: + instrumentationType);
124: }
125:
126: }
127:
128: private void createTHashRemoveAtWrapperMethod(
129: ClassVisitor classVisitor) {
130: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
131: methodName, description, signature, exceptions);
132: addCheckWriteAccessInstrumentedCode(mv, true);
133: mv.visitInsn(ACONST_NULL);
134: mv.visitVarInsn(ASTORE, 2);
135: ByteCodeUtil.pushThis(mv);
136: mv.visitFieldInsn(GETFIELD, ownerSlashes, "_set",
137: "[Ljava/lang/Object;");
138: mv.visitVarInsn(ILOAD, 1);
139: mv.visitInsn(AALOAD);
140: mv.visitVarInsn(ASTORE, 2);
141: ByteCodeUtil.pushThis(mv);
142: Type[] params = Type.getArgumentTypes(description);
143: for (int i = 0; i < params.length; i++) {
144: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
145: }
146: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
147: description);
148:
149: ByteCodeUtil.pushThis(mv);
150:
151: mv.visitLdcInsn(methodName + description);
152: mv.visitLdcInsn(new Integer(1));
153: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
154: mv.visitInsn(DUP);
155: mv.visitLdcInsn(new Integer(0));
156: mv.visitVarInsn(ALOAD, 2);
157: mv.visitInsn(AASTORE);
158: managerHelper.callManagerMethod("logicalInvoke", mv);
159:
160: mv.visitInsn(RETURN);
161: mv.visitMaxs(0, 0);
162: }
163:
164: private void createSortedViewSetWrapper(ClassVisitor classVisitor) {
165: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
166: methodName, description, signature, exceptions);
167: mv.visitTypeInsn(NEW, SortedViewSetWrapper.CLASS_SLASH);
168: mv.visitInsn(DUP);
169: ByteCodeUtil.pushThis(mv);
170: ByteCodeUtil.pushThis(mv);
171: Type[] params = Type.getArgumentTypes(description);
172: for (int i = 0; i < params.length; i++) {
173: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
174: }
175: mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/TreeSet",
176: getNewName(), description);
177: for (int i = 0; i < params.length; i++) {
178: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
179: }
180: if ("headSet".equals(methodName)) {
181: mv.visitInsn(ICONST_1);
182: mv
183: .visitMethodInsn(INVOKESPECIAL,
184: SortedViewSetWrapper.CLASS_SLASH, "<init>",
185: "(Ljava/util/SortedSet;Ljava/util/SortedSet;Ljava/lang/Object;Z)V");
186: } else if ("tailSet".equals(methodName)) {
187: mv.visitInsn(ICONST_0);
188: mv
189: .visitMethodInsn(INVOKESPECIAL,
190: SortedViewSetWrapper.CLASS_SLASH, "<init>",
191: "(Ljava/util/SortedSet;Ljava/util/SortedSet;Ljava/lang/Object;Z)V");
192: } else {
193: mv
194: .visitMethodInsn(
195: INVOKESPECIAL,
196: SortedViewSetWrapper.CLASS_SLASH,
197: "<init>",
198: "(Ljava/util/SortedSet;Ljava/util/SortedSet;Ljava/lang/Object;Ljava/lang/Object;)V");
199: }
200:
201: mv.visitInsn(ARETURN);
202: mv.visitMaxs(0, 0);
203: }
204:
205: private void createSetIteratorWrapper(ClassVisitor classVisitor) {
206: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
207: methodName, description, signature, exceptions);
208: mv.visitTypeInsn(NEW, "com/tc/util/SetIteratorWrapper");
209: mv.visitInsn(DUP);
210: mv.visitVarInsn(ALOAD, 0);
211: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
212: "()Ljava/util/Iterator;");
213: mv.visitVarInsn(ALOAD, 0);
214: mv.visitMethodInsn(INVOKESPECIAL,
215: "com/tc/util/SetIteratorWrapper", "<init>",
216: "(Ljava/util/Iterator;Ljava/util/Set;)V");
217: mv.visitInsn(ARETURN);
218: mv.visitMaxs(0, 0);
219: }
220:
221: private void createEntrySetWrapper(ClassVisitor classVisitor) {
222: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
223: methodName, description, signature, exceptions);
224: Label l0 = new Label();
225: mv.visitLabel(l0);
226: mv.visitTypeInsn(NEW, MapEntrySetWrapper.CLASS_SLASH);
227: mv.visitInsn(DUP);
228: mv.visitVarInsn(ALOAD, 0);
229: mv.visitInsn(DUP);
230: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
231: "()Ljava/util/Set;");
232: mv.visitMethodInsn(INVOKESPECIAL,
233: MapEntrySetWrapper.CLASS_SLASH, "<init>",
234: "(Ljava/util/Map;Ljava/util/Set;)V");
235: mv.visitInsn(ARETURN);
236: Label l1 = new Label();
237: mv.visitLabel(l1);
238: mv.visitLocalVariable("this", "Ljava/util/Map;", null, l0, l1,
239: 0);
240: mv.visitMaxs(5, 1);
241: }
242:
243: private void createKeySetWrapper(ClassVisitor classVisitor) {
244: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
245: methodName, description, signature, exceptions);
246: Label l0 = new Label();
247: mv.visitLabel(l0);
248: mv.visitTypeInsn(NEW, "com/tc/util/THashMapCollectionWrapper");
249: mv.visitInsn(DUP);
250: mv.visitVarInsn(ALOAD, 0);
251: mv.visitInsn(DUP);
252: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
253: "()Ljava/util/Set;");
254: mv.visitMethodInsn(INVOKESPECIAL,
255: "com/tc/util/THashMapCollectionWrapper", "<init>",
256: "(Ljava/util/Map;Ljava/util/Collection;)V");
257: mv.visitInsn(ARETURN);
258: Label l1 = new Label();
259: mv.visitLabel(l1);
260: mv.visitLocalVariable("this", "Ljava/util/Map;", null, l0, l1,
261: 0);
262: mv.visitMaxs(5, 1);
263: }
264:
265: private void createValuesWrapper(ClassVisitor classVisitor) {
266: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
267: methodName, description, signature, exceptions);
268: Label l0 = new Label();
269: mv.visitLabel(l0);
270: mv.visitTypeInsn(NEW, "com/tc/util/THashMapCollectionWrapper");
271: mv.visitInsn(DUP);
272: mv.visitVarInsn(ALOAD, 0);
273: mv.visitInsn(DUP);
274: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
275: "()Ljava/util/Collection;");
276: mv.visitMethodInsn(INVOKESPECIAL,
277: "com/tc/util/THashMapCollectionWrapper", "<init>",
278: "(Ljava/util/Map;Ljava/util/Collection;)V");
279: mv.visitInsn(ARETURN);
280: Label l1 = new Label();
281: mv.visitLabel(l1);
282: mv.visitLocalVariable("this", "Ljava/util/Map;", null, l0, l1,
283: 0);
284: mv.visitMaxs(5, 1);
285: }
286:
287: private void createTHashSetAddWrapperMethod(
288: ClassVisitor classVisitor) {
289: createTHashSetRemoveMethod(classVisitor);
290: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
291: methodName, description, signature, exceptions);
292: addCheckWriteAccessInstrumentedCode(mv, true);
293: mv.visitInsn(ACONST_NULL);
294: mv.visitVarInsn(ASTORE, 2);
295:
296: ByteCodeUtil.pushThis(mv);
297: mv.visitVarInsn(ALOAD, 1);
298: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, "contains",
299: "(Ljava/lang/Object;)Z");
300: Label l2 = new Label();
301: mv.visitJumpInsn(IFEQ, l2);
302: ByteCodeUtil.pushThis(mv);
303: mv.visitFieldInsn(GETFIELD, ownerSlashes, "_set",
304: "[Ljava/lang/Object;");
305: ByteCodeUtil.pushThis(mv);
306: mv.visitVarInsn(ALOAD, 1);
307: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, "index",
308: "(Ljava/lang/Object;)I");
309: mv.visitInsn(AALOAD);
310: mv.visitVarInsn(ASTORE, 2);
311: mv.visitLabel(l2);
312: ByteCodeUtil.pushThis(mv);
313: Type[] params = Type.getArgumentTypes(description);
314: for (int i = 0; i < params.length; i++) {
315: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
316: }
317: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
318: description);
319: Type ret = Type.getReturnType(description);
320: mv.visitVarInsn(ret.getOpcode(ISTORE), 3);
321:
322: ByteCodeUtil.pushThis(mv);
323: mv.visitLdcInsn(methodName + description);
324: mv.visitLdcInsn(new Integer(2));
325: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
326: mv.visitInsn(DUP);
327: int count = 0;
328: mv.visitLdcInsn(new Integer(count++));
329: mv.visitVarInsn(ALOAD, 2);
330: mv.visitInsn(AASTORE);
331:
332: mv.visitInsn(DUP);
333: mv.visitLdcInsn(new Integer(count++));
334: mv.visitVarInsn(ALOAD, 1);
335: mv.visitInsn(AASTORE);
336:
337: managerHelper.callManagerMethod("logicalInvoke", mv);
338:
339: mv.visitVarInsn(ret.getOpcode(ILOAD), 3);
340: mv.visitInsn(ret.getOpcode(IRETURN));
341: mv.visitMaxs(0, 0);
342: }
343:
344: private void createTHashSetRemoveMethod(ClassVisitor classVisitor) {
345: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
346: "removeAt", "(I)V", null, null);
347: addCheckWriteAccessInstrumentedCode(mv, true);
348: ByteCodeUtil.pushThis(mv);
349: mv.visitFieldInsn(GETFIELD, ownerSlashes, "_set",
350: "[Ljava/lang/Object;");
351: mv.visitVarInsn(ILOAD, 1);
352: mv.visitInsn(AALOAD);
353: mv.visitVarInsn(ASTORE, 2);
354: ByteCodeUtil.pushThis(mv);
355: Type[] params = Type.getArgumentTypes("(I)V");
356: for (int i = 0; i < params.length; i++) {
357: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
358: }
359: mv.visitMethodInsn(INVOKESPECIAL, "gnu/trove/TObjectHash",
360: "removeAt", "(I)V");
361:
362: ByteCodeUtil.pushThis(mv);
363:
364: mv.visitLdcInsn("removeAt" + "(I)V");
365: mv.visitLdcInsn(new Integer(1));
366: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
367: mv.visitInsn(DUP);
368: mv.visitLdcInsn(new Integer(0));
369: mv.visitVarInsn(ALOAD, 2);
370: mv.visitInsn(AASTORE);
371: managerHelper.callManagerMethod("logicalInvoke", mv);
372:
373: mv.visitInsn(RETURN);
374: mv.visitMaxs(0, 0);
375: }
376:
377: private void createTHashMapPutWrapperMethod(
378: ClassVisitor classVisitor) {
379: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
380: methodName, description, signature, exceptions);
381: addCheckWriteAccessInstrumentedCode(mv, true);
382: mv.visitInsn(ACONST_NULL);
383: mv.visitVarInsn(ASTORE, 3);
384: ByteCodeUtil.pushThis(mv);
385: mv.visitVarInsn(ALOAD, 1);
386: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, "containsKey",
387: "(Ljava/lang/Object;)Z");
388: Label l2 = new Label();
389: mv.visitJumpInsn(IFEQ, l2);
390: ByteCodeUtil.pushThis(mv);
391: mv.visitFieldInsn(GETFIELD, ownerSlashes, "_set",
392: "[Ljava/lang/Object;");
393: ByteCodeUtil.pushThis(mv);
394: mv.visitVarInsn(ALOAD, 1);
395: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, "index",
396: "(Ljava/lang/Object;)I");
397: mv.visitInsn(AALOAD);
398: mv.visitVarInsn(ASTORE, 3);
399: mv.visitLabel(l2);
400: ByteCodeUtil.pushThis(mv);
401: Type[] params = Type.getArgumentTypes(description);
402: for (int i = 0; i < params.length; i++) {
403: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
404: }
405: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
406: description);
407:
408: mv.visitVarInsn(ASTORE, 4);
409:
410: ByteCodeUtil.pushThis(mv);
411: mv.visitLdcInsn(methodName + description);
412: mv.visitLdcInsn(new Integer(3));
413: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
414: mv.visitInsn(DUP);
415: int count = 0;
416: mv.visitLdcInsn(new Integer(count++));
417: mv.visitVarInsn(ALOAD, 3);
418: mv.visitInsn(AASTORE);
419:
420: mv.visitInsn(DUP);
421: mv.visitLdcInsn(new Integer(count++));
422: mv.visitVarInsn(ALOAD, 1);
423: mv.visitInsn(AASTORE);
424:
425: mv.visitInsn(DUP);
426: mv.visitLdcInsn(new Integer(count++));
427: mv.visitVarInsn(ALOAD, 2);
428: mv.visitInsn(AASTORE);
429:
430: managerHelper.callManagerMethod("logicalInvoke", mv);
431:
432: mv.visitVarInsn(ALOAD, 4);
433: mv.visitInsn(ARETURN);
434: mv.visitMaxs(0, 0);
435: }
436:
437: private void createHashPutWrapperMethod(ClassVisitor classVisitor,
438: boolean checkWriteAccessRequired) {
439: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
440: methodName, description, signature, exceptions);
441: if (checkWriteAccessRequired) {
442: addCheckWriteAccessInstrumentedCode(mv, true);
443: }
444:
445: // run the local put()
446: ByteCodeUtil.pushThis(mv);
447: Type[] params = Type.getArgumentTypes(description);
448: for (int i = 0; i < params.length; i++) {
449: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
450: }
451: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
452: description);
453: mv.visitVarInsn(ASTORE, params.length + 1);
454:
455: // record the logical action if this map managed
456: Label notManaged = new Label();
457: ByteCodeUtil.pushThis(mv);
458: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes,
459: ClassAdapterBase.MANAGED_METHOD,
460: "()Lcom/tc/object/TCObject;");
461: mv.visitJumpInsn(IFNULL, notManaged);
462: ByteCodeUtil.pushThis(mv);
463: mv.visitLdcInsn(originalMethodName + description);
464: ByteCodeUtil.pushThis(mv);
465: mv.visitVarInsn(ALOAD, 1);
466: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, "getEntry",
467: "(Ljava/lang/Object;)L" + ownerSlashes + "$Entry;");
468: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes + "$Entry",
469: "getKey", "()Ljava/lang/Object;");
470: mv.visitVarInsn(ASTORE, 1);
471: ByteCodeUtil.createParametersToArrayByteCode(mv, params);
472: managerHelper.callManagerMethod("logicalInvoke", mv);
473:
474: mv.visitLabel(notManaged);
475: mv.visitVarInsn(ALOAD, params.length + 1);
476: mv.visitInsn(ARETURN);
477: mv.visitMaxs(0, 0);
478: }
479:
480: private void createHashMapRemoveWrapperMethod(
481: ClassVisitor classVisitor, boolean checkWriteAccessRequired) {
482: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
483: methodName, description, signature, exceptions);
484: if (checkWriteAccessRequired) {
485: addCheckWriteAccessInstrumentedCode(mv, true);
486: }
487: Type[] params = Type.getArgumentTypes(description);
488: Label l0 = new Label();
489: mv.visitLabel(l0);
490: ByteCodeUtil.pushThis(mv);
491: mv.visitVarInsn(ALOAD, 1);
492: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, "getEntry",
493: "(Ljava/lang/Object;)L" + ownerSlashes + "$Entry;");
494: mv.visitVarInsn(ASTORE, 2);
495: mv.visitVarInsn(ALOAD, 2);
496: Label l2 = new Label();
497: mv.visitJumpInsn(IFNULL, l2);
498: ByteCodeUtil.pushThis(mv);
499: mv.visitLdcInsn(originalMethodName + description);
500: mv.visitVarInsn(ALOAD, 2);
501: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes + "$Entry",
502: "getKey", "()Ljava/lang/Object;");
503: mv.visitVarInsn(ASTORE, 1);
504: ByteCodeUtil.createParametersToArrayByteCode(mv, params);
505: managerHelper.callManagerMethod("logicalInvoke", mv);
506: mv.visitLabel(l2);
507: ByteCodeUtil.pushThis(mv);
508: mv.visitVarInsn(ALOAD, 1);
509: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
510: description);
511: mv.visitInsn(ARETURN);
512: mv.visitMaxs(0, 0);
513: }
514:
515: private void createIfTrueLogWrapperMethod(ClassVisitor classVisitor) {
516: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
517: methodName, description, signature, exceptions);
518: addCheckWriteAccessInstrumentedCode(mv, true);
519: Type[] params = Type.getArgumentTypes(description);
520: Type returnType = Type.getReturnType(description);
521: ByteCodeUtil.pushThis(mv);
522: mv.visitVarInsn(ALOAD, 1);
523: mv.visitMethodInsn(INVOKEVIRTUAL, ownerSlashes, getNewName(),
524: description);
525: mv.visitVarInsn(returnType.getOpcode(ISTORE), 2);
526: mv.visitVarInsn(ILOAD, 2);
527: Label l1 = new Label();
528: mv.visitJumpInsn(IFEQ, l1);
529: ByteCodeUtil.pushThis(mv);
530: mv.visitLdcInsn(methodName + description);
531: ByteCodeUtil.createParametersToArrayByteCode(mv, params);
532: managerHelper.callManagerMethod("logicalInvoke", mv);
533: mv.visitLabel(l1);
534: mv.visitVarInsn(returnType.getOpcode(ILOAD), 2);
535: mv.visitInsn(returnType.getOpcode(IRETURN));
536: mv.visitMaxs(0, 0);
537: }
538:
539: private void createAlwaysLogWrapperMethod(
540: ClassVisitor classVisitor, boolean checkWriteAccessRequired) {
541: MethodVisitor mv = classVisitor.visitMethod(wrapperAccess,
542: methodName, description, signature, exceptions);
543: if (checkWriteAccessRequired) {
544: addCheckWriteAccessInstrumentedCode(mv, true);
545: }
546: Label l0 = new Label();
547: mv.visitLabel(l0);
548: ByteCodeUtil.pushThis(mv);
549: Type[] params = Type.getArgumentTypes(description);
550: Type returnType = Type.getReturnType(description);
551: for (int i = 0; i < params.length; i++) {
552: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
553: }
554:
555: mv.visitMethodInsn(INVOKESPECIAL, ownerSlashes, getNewName(),
556: description);
557: if (!returnType.equals(Type.VOID_TYPE)) {
558: mv.visitVarInsn(returnType.getOpcode(ISTORE),
559: params.length + 1);
560: }
561: ByteCodeUtil.pushThis(mv);
562: mv.visitLdcInsn(originalMethodName + description);
563:
564: ByteCodeUtil.createParametersToArrayByteCode(mv, params);
565: managerHelper.callManagerMethod("logicalInvoke", mv);
566:
567: if (!returnType.equals(Type.VOID_TYPE)) {
568: mv.visitVarInsn(returnType.getOpcode(ILOAD),
569: params.length + 1);
570: }
571: mv.visitInsn(returnType.getOpcode(IRETURN));
572: mv.visitMaxs(0, 0);
573: }
574:
575: protected void addCheckWriteAccessInstrumentedCode(
576: MethodVisitor mv, boolean checkManaged) {
577: Label notManaged = new Label();
578:
579: if (checkManaged) {
580: ByteCodeUtil.pushThis(mv);
581: mv.visitMethodInsn(INVOKEVIRTUAL, getOwnerSlashes(),
582: ClassAdapterBase.MANAGED_METHOD,
583: "()Lcom/tc/object/TCObject;");
584: mv.visitJumpInsn(IFNULL, notManaged);
585: }
586: ByteCodeUtil.pushThis(mv);
587: managerHelper.callManagerMethod("checkWriteAccess", mv);
588: mv.visitLabel(notManaged);
589: }
590:
591: protected int getInstrumentationType() {
592: return instrumentationType;
593: }
594:
595: protected int getAccess() {
596: return access;
597: }
598:
599: protected String getDescription() {
600: return description;
601: }
602:
603: protected String[] getExceptions() {
604: return exceptions;
605: }
606:
607: protected ManagerHelper getManagerHelper() {
608: return managerHelper;
609: }
610:
611: protected String getMethodName() {
612: return methodName;
613: }
614:
615: protected String getOwnerSlashes() {
616: return ownerSlashes;
617: }
618:
619: protected String getSignature() {
620: return signature;
621: }
622:
623: protected int getWrapperAccess() {
624: return wrapperAccess;
625: }
626:
627: protected String getOriginalMethodName() {
628: return originalMethodName;
629: }
630: }
|