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.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.Label;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012:
013: public class JavaUtilConcurrentHashMapWriteThroughEntryAdapter extends
014: ClassAdapter implements Opcodes {
015: public JavaUtilConcurrentHashMapWriteThroughEntryAdapter(
016: ClassVisitor cv) {
017: super (cv);
018: }
019:
020: public void visit(int version, int access, String name,
021: String signature, String super Name, String[] interfaces) {
022: String[] interfacesNew = new String[interfaces.length + 1];
023: System.arraycopy(interfaces, 0, interfacesNew, 0,
024: interfaces.length);
025: interfacesNew[interfacesNew.length - 1] = TCMapEntry.class
026: .getName().replace('.', '/');
027: super .visit(version, access, name, signature, super Name,
028: interfacesNew);
029: }
030:
031: public void visitEnd() {
032: createGetValueMethod();
033: createTCRawSetValueMethod();
034: createTCIsFaultedInMethod();
035:
036: super .visitEnd();
037: }
038:
039: private void createGetValueMethod() {
040: MethodVisitor mv = super .visitMethod(ACC_PUBLIC, "getValue",
041: "()Ljava/lang/Object;", null, null);
042: mv.visitCode();
043: mv.visitVarInsn(ALOAD, 0);
044: mv.visitMethodInsn(INVOKESPECIAL,
045: "java/util/AbstractMap$SimpleEntry", "getValue",
046: "()Ljava/lang/Object;");
047: mv.visitVarInsn(ASTORE, 1);
048: mv.visitVarInsn(ALOAD, 1);
049: mv.visitTypeInsn(INSTANCEOF, "com/tc/object/ObjectID");
050: Label labelNotObjectID = new Label();
051: mv.visitJumpInsn(IFEQ, labelNotObjectID);
052: mv.visitVarInsn(ALOAD, 1);
053: mv.visitTypeInsn(CHECKCAST, "com/tc/object/ObjectID");
054: mv.visitMethodInsn(INVOKESTATIC,
055: "com/tc/object/bytecode/ManagerUtil", "lookupObject",
056: "(Lcom/tc/object/ObjectID;)Ljava/lang/Object;");
057: mv.visitVarInsn(ASTORE, 1);
058: mv.visitVarInsn(ALOAD, 0);
059: mv.visitVarInsn(ALOAD, 1);
060: mv.visitMethodInsn(INVOKESPECIAL,
061: "java/util/AbstractMap$SimpleEntry", "setValue",
062: "(Ljava/lang/Object;)Ljava/lang/Object;");
063: mv.visitInsn(POP);
064: mv.visitLabel(labelNotObjectID);
065: mv.visitVarInsn(ALOAD, 1);
066: mv.visitInsn(ARETURN);
067: mv.visitMaxs(1, 2);
068: mv.visitEnd();
069: }
070:
071: private void createTCRawSetValueMethod() {
072: MethodVisitor mv = super .visitMethod(ACC_PUBLIC
073: | ACC_SYNCHRONIZED,
074: TCMapEntry.TC_RAWSETVALUE_METHOD_NAME,
075: TCMapEntry.TC_RAWSETVALUE_METHOD_DESC, null, null);
076: mv.visitCode();
077:
078: // set the value in the parent SimpleEntry
079: mv.visitVarInsn(ALOAD, 0);
080: mv.visitVarInsn(ALOAD, 1);
081: mv.visitMethodInsn(INVOKESPECIAL,
082: "java/util/AbstractMap$SimpleEntry", "setValue",
083: "(Ljava/lang/Object;)Ljava/lang/Object;");
084: mv.visitInsn(POP);
085:
086: // push the new value into the outer ConcurrentHashMap instance
087: mv.visitVarInsn(ALOAD, 0);
088: mv
089: .visitFieldInsn(
090: GETFIELD,
091: "java/util/concurrent/ConcurrentHashMap$WriteThroughEntry",
092: "this$0",
093: "Ljava/util/concurrent/ConcurrentHashMap;");
094: mv.visitVarInsn(ALOAD, 0);
095: mv
096: .visitMethodInsn(
097: INVOKEVIRTUAL,
098: "java/util/concurrent/ConcurrentHashMap$WriteThroughEntry",
099: "getKey", "()Ljava/lang/Object;");
100: mv.visitVarInsn(ALOAD, 1);
101: mv.visitMethodInsn(INVOKEVIRTUAL,
102: "java/util/concurrent/ConcurrentHashMap",
103: "__tc_applicator_put",
104: "(Ljava/lang/Object;Ljava/lang/Object;)V");
105:
106: mv.visitInsn(RETURN);
107: mv.visitMaxs(2, 2);
108: mv.visitEnd();
109: }
110:
111: private void createTCIsFaultedInMethod() {
112: MethodVisitor mv = super .visitMethod(ACC_PUBLIC
113: | ACC_SYNCHRONIZED,
114: TCMapEntry.TC_ISVALUEFAULTEDIN_METHOD_NAME,
115: TCMapEntry.TC_ISVALUEFAULTEDIN_METHOD_DESC, null, null);
116: mv.visitCode();
117: mv.visitVarInsn(ALOAD, 0);
118: mv.visitMethodInsn(INVOKESPECIAL,
119: "java/util/AbstractMap$SimpleEntry", "getValue",
120: "()Ljava/lang/Object;");
121: mv.visitTypeInsn(INSTANCEOF, "com/tc/object/ObjectID");
122:
123: Label labelTrue = new Label();
124: mv.visitJumpInsn(IFEQ, labelTrue);
125: mv.visitInsn(ICONST_0);
126: Label labelFalse = new Label();
127: mv.visitJumpInsn(GOTO, labelFalse);
128: mv.visitLabel(labelTrue);
129: mv.visitInsn(ICONST_1);
130: mv.visitLabel(labelFalse);
131:
132: mv.visitInsn(IRETURN);
133: mv.visitMaxs(1, 1);
134: mv.visitEnd();
135: }
136: }
|