1 4 package com.tc.object.bytecode; 5 6 import com.tc.asm.ClassAdapter; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.Label; 9 import com.tc.asm.MethodVisitor; 10 import com.tc.asm.Opcodes; 11 import com.tc.asm.Type; 12 import com.tc.asm.commons.LocalVariablesSorter; 13 import com.tc.object.lockmanager.api.LockLevel; 14 15 public class DSOUnsafeAdapter extends ClassAdapter implements Opcodes, ClassAdapterFactory { 16 17 public DSOUnsafeAdapter() { 18 super(null); 19 } 20 21 private DSOUnsafeAdapter(ClassVisitor cv, ClassLoader loader) { 22 super(cv); 23 } 24 25 public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) { 26 return new DSOUnsafeAdapter(visitor, loader); 27 } 28 29 public final void visit(int version, int access, String name, String signature, String superName, String [] interfaces) { 30 superName = "sun/misc/Unsafe"; 31 super.visit(version, access, name, signature, superName, interfaces); 32 } 33 34 public void visitEnd() { 35 MethodVisitor mv = super.visitMethod(ACC_PUBLIC, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", null, null); 36 addUnsafeWrapperMethodCode(mv, ACC_PUBLIC, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z"); 37 38 mv = super.visitMethod(ACC_PUBLIC, "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", null, null); 39 addUnsafeWrapperMethodCode(mv, ACC_PUBLIC, "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z"); 40 41 42 mv = super.visitMethod(ACC_PUBLIC, "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", null, null); 43 addUnsafeWrapperMethodCode(mv, ACC_PUBLIC, "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"); 44 45 super.visitEnd(); 46 } 47 48 private void addBeginVolatileInstrumentedCode(MethodVisitor mv, Type[] params) { 49 int pos = 0; 50 mv.visitVarInsn(params[0].getOpcode(ILOAD), pos+1); 51 pos += params[0].getSize(); 52 mv.visitVarInsn(params[1].getOpcode(ILOAD), pos+1); 53 mv.visitIntInsn(BIPUSH, LockLevel.WRITE); 54 mv.visitMethodInsn(INVOKESTATIC, "com/tc/object/bytecode/ManagerUtil", "beginVolatileByOffset", 55 "(Ljava/lang/Object;JI)V"); 56 } 57 58 private void addCommitVolatileInstrumentedCode(MethodVisitor mv, Type[] params) { 59 int pos = 0; 60 mv.visitVarInsn(params[0].getOpcode(ILOAD), pos+1); 61 pos += params[0].getSize(); 62 mv.visitVarInsn(params[1].getOpcode(ILOAD), pos+1); 63 mv.visitMethodInsn(INVOKESTATIC, "com/tc/object/bytecode/ManagerUtil", "commitVolatileByOffset", 64 "(Ljava/lang/Object;J)V"); 65 } 66 67 private void addCheckedManagedConditionCode(MethodVisitor mv, Type[] params, int objParamIndex, 68 Label nonSharedLabel, Label sharedLabel) { 69 mv.visitVarInsn(params[objParamIndex].getOpcode(ILOAD), objParamIndex + 1); 70 mv.visitMethodInsn(INVOKESTATIC, "com/tc/object/bytecode/ManagerUtil", "isManaged", 71 "(Ljava/lang/Object;)Z"); 72 mv.visitJumpInsn(IFEQ, nonSharedLabel); 73 mv.visitJumpInsn(GOTO, sharedLabel); 74 } 75 76 private int getParameterPosition(Type[] params, int index) { 77 int pos = 0; 78 for (int i=0; i<index; i++) { 79 pos += params[i].getSize(); 80 } 81 return pos; 82 } 83 84 private void addUnsafeWrapperMethodCode(MethodVisitor mv, int access, String methodName, String description) { 85 mv = new FieldMethodAdapter(access, description, mv); 86 87 Type[] params = Type.getArgumentTypes(description); 88 Type returnType = Type.getReturnType(description); 89 90 int newLocalVar1 = ((FieldMethodAdapter)mv).addNewVar(1); 91 int newLocalVar2 = ((FieldMethodAdapter)mv).addNewVar(1); 92 int newLocalVar3 = ((FieldMethodAdapter)mv).addNewVar(1); 93 94 mv.visitCode(); 95 96 Label l0 = new Label(); 97 Label l1 = new Label(); 98 mv.visitTryCatchBlock(l0, l1, l1, null); 99 Label l2 = new Label(); 100 Label l3 = new Label(); 101 mv.visitTryCatchBlock(l2, l3, l1, null); 102 Label l4 = new Label(); 103 mv.visitLabel(l4); 104 Label l5 = new Label(); 105 Label l6 = new Label(); 106 addCheckedManagedConditionCode(mv, params, 0, l6, l5); 107 108 mv.visitLabel(l6); 109 invokeSuperMethod(mv, methodName, description, params); 110 mv.visitInsn(returnType.getOpcode(IRETURN)); 111 112 mv.visitLabel(l5); 113 mv.visitInsn(ICONST_0); 114 mv.visitVarInsn(ISTORE, newLocalVar1); 115 116 Label l7 = new Label(); 117 mv.visitLabel(l7); 118 addBeginVolatileInstrumentedCode(mv, params); 119 120 mv.visitLabel(l0); 121 invokeSuperMethod(mv, methodName, description, params); 122 mv.visitVarInsn(ISTORE, newLocalVar1); 123 124 Label l8 = new Label(); 125 mv.visitLabel(l8); 126 mv.visitVarInsn(ILOAD, newLocalVar1); 127 mv.visitJumpInsn(IFEQ, l2); 128 129 Label l9 = new Label(); 130 mv.visitLabel(l9); 131 mv.visitVarInsn(params[0].getOpcode(ILOAD), getParameterPosition(params, 0)+1); 132 mv.visitVarInsn(params[1].getOpcode(ILOAD), getParameterPosition(params, 1)+1); 133 ByteCodeUtil.addTypeSpecificParameterLoad(mv, params[3], getParameterPosition(params, 3)+1); 134 mv.visitMethodInsn(INVOKESTATIC, "com/tc/util/UnsafeUtil", "updateDSOSharedField", "(Ljava/lang/Object;JLjava/lang/Object;)V"); 135 mv.visitJumpInsn(GOTO, l2); 136 137 mv.visitLabel(l1); 138 mv.visitVarInsn(ASTORE, newLocalVar3); 139 Label l10 = new Label(); 140 mv.visitJumpInsn(JSR, l10); 141 Label l11 = new Label(); 142 mv.visitLabel(l11); 143 mv.visitVarInsn(ALOAD, newLocalVar3); 144 mv.visitInsn(ATHROW); 145 mv.visitLabel(l10); 146 mv.visitVarInsn(ASTORE, newLocalVar2); 147 Label l12 = new Label(); 148 mv.visitLabel(l12); 149 addCommitVolatileInstrumentedCode(mv, params); 150 Label l13 = new Label(); 151 mv.visitLabel(l13); 152 mv.visitVarInsn(RET, newLocalVar2); 153 154 mv.visitLabel(l2); 155 mv.visitJumpInsn(JSR, l10); 156 mv.visitLabel(l3); 157 mv.visitVarInsn(ILOAD, newLocalVar1); 158 mv.visitInsn(returnType.getOpcode(IRETURN)); 159 Label l14 = new Label(); 160 mv.visitLabel(l14); 161 mv.visitMaxs(0, 0); 162 mv.visitEnd(); 163 } 164 165 protected void addCheckWriteAccessInstrumentedCode(MethodVisitor mv, Type[] params, int objParamIndex) { 166 mv.visitVarInsn(params[objParamIndex].getOpcode(ILOAD), objParamIndex + 1); 167 mv.visitMethodInsn(INVOKESTATIC, "com/tc/object/bytecode/ManagerUtil", "checkWriteAccess", 168 "(Ljava/lang/Object;)V"); 169 } 170 171 private void invokeSuperMethod(MethodVisitor mv, String methodName, String description, Type[] params) { 172 ByteCodeUtil.pushThis(mv); 173 int pos = 0; 174 for (int i = 0; i < params.length; i++) { 175 mv.visitVarInsn(params[i].getOpcode(ILOAD), pos+1); 176 pos += params[i].getSize(); 177 } 178 mv.visitMethodInsn(INVOKESPECIAL, "sun/misc/Unsafe", methodName, description); 179 } 180 181 private class FieldMethodAdapter extends LocalVariablesSorter implements Opcodes { 182 public FieldMethodAdapter(int access, String desc, MethodVisitor mv) { 183 super(access, desc, mv); 184 } 185 186 public int addNewVar(int size) { 187 return newLocal(size); 188 } 189 } 190 191 } 192 | Popular Tags |