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.ClassAdapter;
007: import com.tc.asm.ClassVisitor;
008: import com.tc.asm.Label;
009: import com.tc.asm.MethodVisitor;
010: import com.tc.asm.Opcodes;
011: import com.tc.asm.Type;
012: import com.tc.asm.commons.LocalVariablesSorter;
013: import com.tc.object.bytecode.JavaUtilConcurrentLinkedBlockingQueueClassAdapter.NodeMethodAdapter;
014:
015: public class JavaUtilConcurrentLinkedBlockingQueueIteratorClassAdapter
016: extends ClassAdapter implements Opcodes {
017:
018: public JavaUtilConcurrentLinkedBlockingQueueIteratorClassAdapter(
019: ClassVisitor cv) {
020: super (cv);
021: }
022:
023: public MethodVisitor visitMethod(int access, String name,
024: String desc, String signature, String[] exceptions) {
025: MethodVisitor mv = super .visitMethod(access, name, desc,
026: signature, exceptions);
027: mv = new NodeMethodAdapter(mv);
028: if ("remove".equals(name) && "()V".equals(desc)) {
029: mv = new RemoveMethodAdapter(access, desc, mv);
030: }
031: return mv;
032: }
033:
034: // This is a hack for the remove() method of the LinkedBlockingQueue.iterator.
035: private static class RemoveMethodAdapter extends
036: LocalVariablesSorter implements Opcodes {
037: private final int newLocalVar;
038: private boolean incNext = false;
039: private boolean incDone = false;
040:
041: public RemoveMethodAdapter(int access, String desc,
042: MethodVisitor mv) {
043: super (access, desc, mv);
044: newLocalVar = newLocal(Type.INT_TYPE);
045: }
046:
047: public void visitCode() {
048: super .visitCode();
049:
050: mv.visitInsn(ICONST_0);
051: mv.visitVarInsn(ISTORE, newLocalVar);
052: }
053:
054: public void visitFieldInsn(int opcode, String owner,
055: String name, String desc) {
056: super .visitFieldInsn(opcode, owner, name, desc);
057: if (GETFIELD == opcode && "next".equals(name)) {
058: if (!incNext) {
059: incNext = true;
060: } else if (!incDone) {
061: mv.visitIincInsn(newLocalVar, 1);
062: incDone = true;
063: }
064: } else if (PUTFIELD == opcode && "item".equals(name)) {
065: addLogicalInvokeMethod();
066: }
067: }
068:
069: private void addLogicalInvokeMethod() {
070: mv.visitVarInsn(ALOAD, 0);
071: mv.visitFieldInsn(GETFIELD,
072: "java/util/concurrent/LinkedBlockingQueue$Itr",
073: "this$0",
074: "Ljava/util/concurrent/LinkedBlockingQueue;");
075: mv.visitMethodInsn(INVOKESTATIC,
076: "com/tc/object/bytecode/ManagerUtil", "isManaged",
077: "(Ljava/lang/Object;)Z");
078: Label l21 = new Label();
079: mv.visitJumpInsn(IFEQ, l21);
080: Label l22 = new Label();
081: mv.visitLabel(l22);
082: mv.visitVarInsn(ALOAD, 0);
083: mv.visitFieldInsn(GETFIELD,
084: "java/util/concurrent/LinkedBlockingQueue$Itr",
085: "this$0",
086: "Ljava/util/concurrent/LinkedBlockingQueue;");
087: mv.visitLdcInsn("remove(I)Ljava/lang/Object;");
088: mv.visitInsn(ICONST_1);
089: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
090: mv.visitInsn(DUP);
091: mv.visitInsn(ICONST_0);
092: mv.visitTypeInsn(NEW, "java/lang/Integer");
093: mv.visitInsn(DUP);
094: mv.visitVarInsn(ILOAD, newLocalVar);
095: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer",
096: "<init>", "(I)V");
097: mv.visitInsn(AASTORE);
098: mv
099: .visitMethodInsn(INVOKESTATIC,
100: "com/tc/object/bytecode/ManagerUtil",
101: "logicalInvoke",
102: "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");
103: mv.visitLabel(l21);
104: }
105: }
106:
107: }
|