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