001: /*
002: * All content copyright (c) 2003-2007 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.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.Label;
010: import com.tc.asm.MethodAdapter;
011: import com.tc.asm.MethodVisitor;
012: import com.tc.asm.Opcodes;
013: import com.tc.asm.Type;
014:
015: public class ReentrantReadWriteLockClassAdapter extends ClassAdapter
016: implements Opcodes {
017: public ReentrantReadWriteLockClassAdapter(ClassVisitor cv) {
018: super (cv);
019: }
020:
021: public final MethodVisitor visitMethod(int access, String name,
022: String desc, String signature, String[] exceptions) {
023: if ("hasQueuedThreads".equals(name)
024: || "hasQueuedThread".equals(name)
025: || "getQueueLength".equals(name)) {
026: name = getNewName(name);
027: }
028:
029: MethodVisitor mv = super .visitMethod(access, name, desc,
030: signature, exceptions);
031: if ("<init>".equals(name)) {
032: mv = new InitMethodAdapter(mv);
033: }
034: return mv;
035: }
036:
037: private String getNewName(String methodName) {
038: return ByteCodeUtil.TC_METHOD_PREFIX + methodName;
039: }
040:
041: public void visitEnd() {
042: createHasQueuedThreadsMethod("hasQueuedThreads", "()Z");
043: createHasQueuedThreadMethod("hasQueuedThread",
044: "(Ljava/lang/Thread;)Z");
045: createGetQueueLengthMethod("getQueueLength", "()I");
046: super .visitEnd();
047: }
048:
049: private void createGetQueueLengthMethod(String methodName,
050: String methodDesc) {
051: Type ret = Type.getReturnType(methodDesc);
052: MethodVisitor mv = super .visitMethod(ACC_PUBLIC + ACC_FINAL,
053: methodName, methodDesc, null, null);
054: mv.visitCode();
055: Label l0 = new Label();
056: mv.visitLabel(l0);
057: mv.visitLineNumber(258, l0);
058: mv.visitVarInsn(ALOAD, 0);
059: mv.visitMethodInsn(INVOKESTATIC,
060: "com/tc/object/bytecode/ManagerUtil", "isManaged",
061: "(Ljava/lang/Object;)Z");
062: Label l1 = new Label();
063: mv.visitJumpInsn(IFEQ, l1);
064: Label l2 = new Label();
065: mv.visitLabel(l2);
066: mv.visitLineNumber(259, l2);
067: mv.visitVarInsn(ALOAD, 0);
068: mv
069: .visitFieldInsn(
070: GETFIELD,
071: "java/util/concurrent/locks/ReentrantReadWriteLock",
072: "sync",
073: "Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;");
074: mv.visitMethodInsn(INVOKESTATIC,
075: "com/tc/object/bytecode/ManagerUtil", "queueLength",
076: "(Ljava/lang/Object;)I");
077: mv.visitInsn(ret.getOpcode(IRETURN));
078: mv.visitLabel(l1);
079: mv.visitLineNumber(261, l1);
080: mv.visitVarInsn(ALOAD, 0);
081: Type[] params = Type.getArgumentTypes(methodDesc);
082: for (int i = 0; i < params.length; i++) {
083: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
084: }
085: mv.visitMethodInsn(INVOKESPECIAL,
086: "java/util/concurrent/locks/ReentrantReadWriteLock",
087: getNewName(methodName), methodDesc);
088: mv.visitInsn(ret.getOpcode(IRETURN));
089: Label l4 = new Label();
090: mv.visitLabel(l4);
091: mv.visitMaxs(0, 0);
092: mv.visitEnd();
093: }
094:
095: private void createHasQueuedThreadMethod(String methodName,
096: String methodDesc) {
097: Type ret = Type.getReturnType(methodDesc);
098: MethodVisitor mv = super .visitMethod(ACC_PUBLIC + ACC_FINAL,
099: methodName, methodDesc, null, null);
100: mv.visitCode();
101: Label l0 = new Label();
102: mv.visitLabel(l0);
103: mv.visitLineNumber(258, l0);
104: mv.visitVarInsn(ALOAD, 0);
105: mv.visitMethodInsn(INVOKESTATIC,
106: "com/tc/object/bytecode/ManagerUtil", "isManaged",
107: "(Ljava/lang/Object;)Z");
108: Label l1 = new Label();
109: mv.visitJumpInsn(IFEQ, l1);
110: Label l2 = new Label();
111: mv.visitLabel(l2);
112: mv.visitLineNumber(259, l2);
113: mv.visitTypeInsn(NEW,
114: "com/tc/exception/TCNotSupportedMethodException");
115: mv.visitInsn(DUP);
116: mv.visitMethodInsn(INVOKESPECIAL,
117: "com/tc/exception/TCNotSupportedMethodException",
118: "<init>", "()V");
119: mv.visitInsn(ATHROW);
120: mv.visitLabel(l1);
121: mv.visitLineNumber(261, l1);
122: mv.visitVarInsn(ALOAD, 0);
123: Type[] params = Type.getArgumentTypes(methodDesc);
124: for (int i = 0; i < params.length; i++) {
125: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
126: }
127: mv.visitMethodInsn(INVOKESPECIAL,
128: "java/util/concurrent/locks/ReentrantReadWriteLock",
129: getNewName(methodName), methodDesc);
130: mv.visitInsn(ret.getOpcode(IRETURN));
131: Label l4 = new Label();
132: mv.visitLabel(l4);
133: mv.visitMaxs(0, 0);
134: mv.visitEnd();
135: }
136:
137: private void createHasQueuedThreadsMethod(String methodName,
138: String methodDesc) {
139: Type ret = Type.getReturnType(methodDesc);
140: MethodVisitor mv = super .visitMethod(ACC_PUBLIC + ACC_FINAL,
141: methodName, methodDesc, null, null);
142: mv.visitCode();
143: Label l0 = new Label();
144: mv.visitLabel(l0);
145: mv.visitLineNumber(258, l0);
146: mv.visitVarInsn(ALOAD, 0);
147: mv.visitMethodInsn(INVOKESTATIC,
148: "com/tc/object/bytecode/ManagerUtil", "isManaged",
149: "(Ljava/lang/Object;)Z");
150: Label l1 = new Label();
151: mv.visitJumpInsn(IFEQ, l1);
152: Label l2 = new Label();
153: mv.visitLabel(l2);
154: mv.visitLineNumber(259, l2);
155: mv.visitVarInsn(ALOAD, 0);
156: mv
157: .visitFieldInsn(
158: GETFIELD,
159: "java/util/concurrent/locks/ReentrantReadWriteLock",
160: "sync",
161: "Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;");
162: mv.visitMethodInsn(INVOKESTATIC,
163: "com/tc/object/bytecode/ManagerUtil", "queueLength",
164: "(Ljava/lang/Object;)I");
165: Label l3 = new Label();
166: mv.visitJumpInsn(IFLE, l3);
167: mv.visitInsn(ICONST_1);
168: mv.visitInsn(ret.getOpcode(IRETURN));
169: mv.visitLabel(l3);
170: mv.visitInsn(ICONST_0);
171: mv.visitInsn(ret.getOpcode(IRETURN));
172: mv.visitLabel(l1);
173: mv.visitLineNumber(261, l1);
174: mv.visitVarInsn(ALOAD, 0);
175: Type[] params = Type.getArgumentTypes(methodDesc);
176: for (int i = 0; i < params.length; i++) {
177: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
178: }
179: mv.visitMethodInsn(INVOKESPECIAL,
180: "java/util/concurrent/locks/ReentrantReadWriteLock",
181: getNewName(methodName), methodDesc);
182: mv.visitInsn(ret.getOpcode(IRETURN));
183: Label l4 = new Label();
184: mv.visitLabel(l4);
185: mv.visitMaxs(0, 0);
186: mv.visitEnd();
187: }
188:
189: private final static class InitMethodAdapter extends MethodAdapter
190: implements Opcodes {
191: public InitMethodAdapter(MethodVisitor mv) {
192: super (mv);
193: }
194:
195: public void visitTypeInsn(int opcode, String desc) {
196: if (NEW == opcode) {
197: if ("java/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync"
198: .equals(desc)) {
199: desc = "java/util/concurrent/locks/ReentrantReadWriteLock$FairSync";
200: } else if ("java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock"
201: .equals(desc)) {
202: desc = "java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock";
203: } else if ("java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock"
204: .equals(desc)) {
205: desc = "java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock";
206: }
207: }
208: super .visitTypeInsn(opcode, desc);
209: }
210:
211: public void visitMethodInsn(int opcode, String owner,
212: String name, String desc) {
213: if (opcode == INVOKESPECIAL) {
214: if ("java/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync"
215: .equals(owner)
216: && "<init>".equals(name) && "()V".equals(desc)) {
217: owner = "java/util/concurrent/locks/ReentrantReadWriteLock$FairSync";
218: } else if ("java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock"
219: .equals(owner)
220: && "<init>".equals(name)
221: && "(Ljava/util/concurrent/locks/ReentrantReadWriteLock;)V"
222: .equals(desc)) {
223: mv.visitVarInsn(ALOAD, 0);
224: mv
225: .visitFieldInsn(
226: GETFIELD,
227: "java/util/concurrent/locks/ReentrantReadWriteLock",
228: "sync",
229: "Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;");
230: //owner = "java/util/concurrent/locks/ReentrantReadWriteLock$ReadLockTC";
231: owner = "java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock";
232: desc = "(Ljava/util/concurrent/locks/ReentrantReadWriteLock;Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;)V";
233: } else if ("java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock"
234: .equals(owner)
235: && "<init>".equals(name)
236: && "(Ljava/util/concurrent/locks/ReentrantReadWriteLock;)V"
237: .equals(desc)) {
238: mv.visitVarInsn(ALOAD, 0);
239: mv
240: .visitFieldInsn(
241: GETFIELD,
242: "java/util/concurrent/locks/ReentrantReadWriteLock",
243: "sync",
244: "Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;");
245: //owner = "java/util/concurrent/locks/ReentrantReadWriteLock$WriteLockTC";
246: owner = "java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock";
247: desc = "(Ljava/util/concurrent/locks/ReentrantReadWriteLock;Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;)V";
248: }
249: }
250: super.visitMethodInsn(opcode, owner, name, desc);
251: }
252: }
253: }
|