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.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.commons.LocalVariablesSorter;
013: import com.tc.object.SerializationUtil;
014:
015: public class JavaUtilConcurrentLinkedBlockingQueueAdapter implements
016: Opcodes {
017:
018: public static class PutAdapter extends AbstractMethodAdapter {
019:
020: public MethodVisitor adapt(ClassVisitor classVisitor) {
021: return new PutMethodAdapter(access, description,
022: visitOriginal(classVisitor),
023: SerializationUtil.QUEUE_PUT_SIGNATURE);
024: }
025:
026: public boolean doesOriginalNeedAdapting() {
027: return false;
028: }
029: }
030:
031: public static class ClearAdapter extends AbstractMethodAdapter {
032: public MethodVisitor adapt(ClassVisitor classVisitor) {
033: return new ClearMethodAdapter(visitOriginal(classVisitor),
034: SerializationUtil.CLEAR_SIGNATURE);
035: }
036:
037: public boolean doesOriginalNeedAdapting() {
038: return false;
039: }
040: }
041:
042: public static class RemoveFirstNAdapter extends
043: AbstractMethodAdapter {
044: public MethodVisitor adapt(ClassVisitor classVisitor) {
045: return new RemoveFirstNMethodAdapter(
046: visitOriginal(classVisitor),
047: SerializationUtil.REMOVE_FIRST_N_SIGNATURE);
048: }
049:
050: public boolean doesOriginalNeedAdapting() {
051: return false;
052: }
053: }
054:
055: public static class TakeAdapter extends AbstractMethodAdapter {
056:
057: public MethodVisitor adapt(ClassVisitor classVisitor) {
058: return new TakeMethodAdapter(visitOriginal(classVisitor),
059: SerializationUtil.TAKE_SIGNATURE);
060: }
061:
062: public boolean doesOriginalNeedAdapting() {
063: return false;
064: }
065: }
066:
067: private static class ClearMethodAdapter extends MethodAdapter
068: implements Opcodes {
069: private final String invokeMethodSignature;
070:
071: public ClearMethodAdapter(MethodVisitor mv,
072: String invokeMethodSignature) {
073: super (mv);
074: this .invokeMethodSignature = invokeMethodSignature;
075: }
076:
077: public void visitFieldInsn(int opcode, String owner,
078: String name, String desc) {
079: super .visitFieldInsn(opcode, owner, name, desc);
080: if (PUTFIELD == opcode && "next".equals(name)) {
081: addLogicalInvokeMethodCall();
082: }
083: }
084:
085: private void addLogicalInvokeMethodCall() {
086: Label notManaged = new Label();
087: addCheckedManagedCode(mv, notManaged);
088: ByteCodeUtil.pushThis(mv);
089:
090: mv.visitLdcInsn(invokeMethodSignature);
091:
092: mv.visitLdcInsn(new Integer(0));
093: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
094: mv
095: .visitMethodInsn(INVOKESTATIC,
096: "com/tc/object/bytecode/ManagerUtil",
097: "logicalInvoke",
098: "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");
099: mv.visitLabel(notManaged);
100: }
101: }
102:
103: private static class RemoveFirstNMethodAdapter extends
104: MethodAdapter implements Opcodes {
105: private final String invokeMethodSignature;
106:
107: public RemoveFirstNMethodAdapter(MethodVisitor mv,
108: String invokeMethodSignature) {
109: super (mv);
110: this .invokeMethodSignature = invokeMethodSignature;
111: }
112:
113: public void visitFieldInsn(int opcode, String owner,
114: String name, String desc) {
115: super .visitFieldInsn(opcode, owner, name, desc);
116: if (PUTFIELD == opcode
117: && "next".equals(name)
118: && "Ljava/util/concurrent/LinkedBlockingQueue$Node;"
119: .equals(desc)) {
120: addLogicalInvokeMethodCall();
121: }
122: }
123:
124: private void addLogicalInvokeMethodCall() {
125: Label notManaged = new Label();
126: addCheckedManagedCode(mv, notManaged);
127: ByteCodeUtil.pushThis(mv);
128:
129: mv.visitLdcInsn(invokeMethodSignature);
130:
131: mv.visitLdcInsn(new Integer(1));
132: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
133:
134: int count = 0;
135: mv.visitInsn(DUP);
136: mv.visitLdcInsn(new Integer(count++));
137: mv.visitTypeInsn(NEW, "java/lang/Integer");
138: mv.visitInsn(DUP);
139: mv.visitVarInsn(ILOAD, 3);
140: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer",
141: "<init>", "(I)V");
142: mv.visitInsn(AASTORE);
143:
144: mv
145: .visitMethodInsn(INVOKESTATIC,
146: "com/tc/object/bytecode/ManagerUtil",
147: "logicalInvoke",
148: "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");
149: mv.visitLabel(notManaged);
150: }
151: }
152:
153: private static class PutMethodAdapter extends LocalVariablesSorter
154: implements Opcodes {
155: private final String invokeMethodSignature;
156: private final Label continueLabel;
157: private boolean visitAddCoded = false;
158: private int newVar;
159:
160: public PutMethodAdapter(final int access, final String desc,
161: final MethodVisitor mv, String invokeMethodSignature) {
162: super (access, desc, mv);
163: this .invokeMethodSignature = invokeMethodSignature;
164: this .continueLabel = new Label();
165: // this.newVar = newLocal(Type.INT_TYPE);
166: this .newVar = 5;
167: }
168:
169: /**
170: * Changing the while (count.get() == capacity) condition to while (count.get() >= capacity) due to the non-blocking
171: * version of __tc_put().
172: */
173: public void visitJumpInsn(int opcode, Label label) {
174: if (IF_ICMPEQ == opcode) {
175: opcode = IF_ICMPGE;
176: } else if (IF_ICMPNE == opcode) { // for jdk higher than 1.5_08
177: opcode = IF_ICMPLT;
178: }
179: super .visitJumpInsn(opcode, label);
180: }
181:
182: public void visitMethodInsn(int opcode, String owner,
183: String name, String desc) {
184: super .visitMethodInsn(opcode, owner, name, desc);
185: if ("insert".equals(name)
186: && "(Ljava/lang/Object;)V".equals(desc)) {
187: addLogicalInvokeMethodCall();
188: } else if (INVOKESPECIAL == opcode
189: && "signalNotEmpty".equals(name)
190: && "()V".equals(desc)) {
191: super .visitInsn(RETURN);
192: }
193: }
194:
195: public void visitInsn(int opcode) {
196: if (RETURN == opcode) {
197: super .visitVarInsn(ILOAD, newVar);
198: Label a = new Label();
199: super .visitJumpInsn(IFNE, a);
200: ByteCodeUtil.pushThis(mv);
201: super .visitMethodInsn(INVOKESPECIAL,
202: "java/util/concurrent/LinkedBlockingQueue",
203: "signalNotEmpty", "()V");
204: super .visitLabel(a);
205: }
206: super .visitInsn(opcode);
207: }
208:
209: private void addLogicalInvokeMethodCall() {
210: Label notManaged = new Label();
211:
212: addCheckedManagedCode(mv, notManaged);
213: super .visitVarInsn(ALOAD, 4);
214: super .visitMethodInsn(INVOKEVIRTUAL,
215: "java/util/concurrent/atomic/AtomicInteger", "get",
216: "()I");
217: super .visitVarInsn(ISTORE, 2);
218: ByteCodeUtil.pushThis(mv);
219: super .visitVarInsn(ALOAD, 3);
220: super .visitLdcInsn(invokeMethodSignature);
221: super .visitInsn(ICONST_1);
222: super .visitTypeInsn(ANEWARRAY, "java/lang/Object");
223: super .visitInsn(DUP);
224: super .visitInsn(ICONST_0);
225: super .visitVarInsn(ALOAD, 1);
226: super .visitInsn(AASTORE);
227: super
228: .visitMethodInsn(INVOKESTATIC,
229: "com/tc/object/bytecode/ManagerUtil",
230: "logicalInvokeWithTransaction",
231: "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");
232: super .visitVarInsn(ALOAD, 4);
233: super .visitMethodInsn(INVOKEVIRTUAL,
234: "java/util/concurrent/atomic/AtomicInteger",
235: "getAndIncrement", "()I");
236: super .visitVarInsn(ISTORE, newVar);
237: super .visitJumpInsn(GOTO, continueLabel);
238: super .visitLabel(notManaged);
239: visitAddCoded = true;
240: }
241:
242: public void visitVarInsn(int opcode, int var) {
243: super .visitVarInsn(opcode, var);
244: if (ISTORE == opcode && 2 == var && visitAddCoded) {
245: super .visitLabel(continueLabel);
246: visitAddCoded = false;
247: }
248: }
249: }
250:
251: private static class TakeMethodAdapter extends MethodAdapter
252: implements Opcodes {
253: private boolean visitExtract = false;
254: private final String invokeMethodSignature;
255:
256: public TakeMethodAdapter(MethodVisitor mv,
257: String invokeMethodSignature) {
258: super (mv);
259: this .invokeMethodSignature = invokeMethodSignature;
260: }
261:
262: public void visitJumpInsn(int opcode, Label label) {
263: if (IFEQ == opcode) {
264: opcode = IFLE;
265: } else if (IFNE == opcode) { // for jdk higher than 1.5_08
266: opcode = IFGT;
267: }
268: super .visitJumpInsn(opcode, label);
269: }
270:
271: public void visitMethodInsn(int opcode, String owner,
272: String name, String desc) {
273: super .visitMethodInsn(opcode, owner, name, desc);
274: if ("extract".equals(name)
275: && "()Ljava/lang/Object;".equals(desc)) {
276: visitExtract = true;
277: }
278: }
279:
280: public void visitVarInsn(int opcode, int var) {
281: if (ASTORE == opcode && visitExtract) {
282: super .visitVarInsn(opcode, var);
283: addLogicalInvokeMethodCall();
284: visitExtract = false;
285: } else {
286: super .visitVarInsn(opcode, var);
287: }
288: }
289:
290: private void addLogicalInvokeMethodCall() {
291: Label notManaged = new Label();
292: addCheckedManagedCode(mv, notManaged);
293: ByteCodeUtil.pushThis(mv);
294: ByteCodeUtil.pushThis(mv);
295: mv.visitFieldInsn(GETFIELD,
296: "java/util/concurrent/LinkedBlockingQueue",
297: "takeLock",
298: "Ljava/util/concurrent/locks/ReentrantLock;");
299: mv.visitLdcInsn(invokeMethodSignature);
300:
301: mv.visitLdcInsn(new Integer(0));
302: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
303: mv
304: .visitMethodInsn(INVOKESTATIC,
305: "com/tc/object/bytecode/ManagerUtil",
306: "logicalInvokeWithTransaction",
307: "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");
308: mv.visitLabel(notManaged);
309: }
310: }
311:
312: private static void addCheckedManagedCode(MethodVisitor mv,
313: Label notManaged) {
314: ByteCodeUtil.pushThis(mv);
315: mv.visitMethodInsn(INVOKESTATIC,
316: "com/tc/object/bytecode/ManagerUtil", "isManaged",
317: "(Ljava/lang/Object;)Z");
318: mv.visitJumpInsn(IFEQ, notManaged);
319: }
320: }
|