1 package org.hansel; 2 3 import static org.objectweb.asm.Opcodes.ALOAD; 4 import static org.objectweb.asm.Opcodes.ASTORE; 5 import static org.objectweb.asm.Opcodes.ATHROW; 6 import static org.objectweb.asm.Opcodes.MONITOREXIT; 7 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Vector ; 11 12 import org.objectweb.asm.Label; 13 import org.objectweb.asm.MethodAdapter; 14 import org.objectweb.asm.MethodVisitor; 15 import org.objectweb.asm.Opcodes; 16 import org.objectweb.asm.tree.AbstractInsnNode; 17 import org.objectweb.asm.tree.InsnList; 18 import org.objectweb.asm.tree.LabelNode; 19 import org.objectweb.asm.tree.LineNumberNode; 20 import org.objectweb.asm.tree.TryCatchBlockNode; 21 22 public class HanselCodeAdapter extends MethodAdapter { 23 private boolean first; 24 private int pos; 25 private InsnList instructions; 26 private String className; 27 private String methodName; 28 private HanselFrame[] frames; 29 private List <Probe> probes; 30 private List tryCatchBlocks; 31 private Probe methodProbe; 32 private int access; 33 private ClassLoader loader; 34 35 public HanselCodeAdapter(int access, String className, 36 String methodName, InsnList instructions, List tryCatchBlocks, MethodVisitor mv, 37 HanselFrame[] frames, ClassLoader loader) { 38 super(mv); 39 40 this.access = access; 41 this.first = true; 42 this.pos = 0; 43 this.instructions = instructions; 44 this.className = className; 45 this.methodName = methodName; 46 this.frames = frames; 47 this.probes = new Vector <Probe>(); 48 this.tryCatchBlocks = tryCatchBlocks; 49 this.loader = loader; 50 } 51 52 private void addProbe(Probe probe) { 53 probe.insertProbeCode(mv); 54 probes.add(probe); 55 } 56 57 private void checkFirst() { 58 pos++; 61 62 63 if (!first) { 64 return; 65 } 66 first = false; 67 68 if (!isEmptyPrivateConstructor() && !isStaticConstructor()) { 69 methodProbe = ProbeFactory.createMethodProbe(getProbeData()); 70 addProbe(methodProbe); 71 } 72 } 73 74 private boolean isEmptyPrivateConstructor() { 75 return "<init>".equals(methodName) && 76 ((access & Opcodes.ACC_PRIVATE) > 0) && 77 countRelevantInstructions(instructions) == 3; 78 } 79 80 private int countRelevantInstructions(InsnList instructions) { 81 int count = 0; 82 for (AbstractInsnNode node : instructions.toArray()) { 83 if (!(node instanceof LineNumberNode) && 84 !(node instanceof LabelNode)) { 85 count++; 86 } 87 } 88 return count; 89 } 90 91 private boolean isStaticConstructor() { 92 return "<clinit>".equals(methodName); 93 } 94 95 private ProbeData getProbeData() { 96 return new ProbeData( 97 className, 98 methodName, 99 frames[pos - 1], 100 pos, 101 instructions.size(), 102 loader); 103 } 104 105 public void visitLineNumber(int line, Label start) { 106 super.visitLineNumber(line, start); 107 checkFirst(); 108 109 110 int startIndex = Util.findIndex(instructions, start); 111 112 113 for (int i=0; i<probes.size(); i++) { 114 ProbeData pd = probes.get(i).getProbeData(); 115 if (startIndex < pd.getPosition()) { 116 pd.setLineNumber(line); 117 } 118 } 119 } 120 121 public void visitInsn(final int opcode) { 122 checkFirst(); 123 124 mv.visitInsn(opcode); 125 } 126 127 public void visitIntInsn(final int opcode, final int operand) { 128 checkFirst(); 129 130 mv.visitIntInsn(opcode, operand); 131 } 132 133 public void visitVarInsn(final int opcode, final int var) { 134 checkFirst(); 135 136 mv.visitVarInsn(opcode, var); 137 } 138 139 public void visitFieldInsn(final int opcode, 140 final String owner, 141 final String name, 142 final String desc) { 143 checkFirst(); 144 145 mv.visitFieldInsn(opcode, owner, name, desc); 146 } 147 148 public void visitMethodInsn(final int opcode, 149 final String owner, 150 final String name, 151 final String desc) { 152 checkFirst(); 153 154 mv.visitMethodInsn(opcode, owner, name, desc); 155 } 156 157 public void visitJumpInsn(final int opcode, final Label label) { 158 checkFirst(); 159 160 if (opcode != Opcodes.GOTO) { 161 addProbe(ProbeFactory.createBranchProbe(getProbeData(), 162 opcode)); 163 } 164 165 mv.visitJumpInsn(opcode, label); 166 } 167 168 public void visitLabel(final Label label) { 169 171 pos++; 172 173 mv.visitLabel(label); 174 175 if (isExceptionHandler(label) && !isMonitorExitHandler()) { 176 addProbe(ProbeFactory.createExceptionProbe(getProbeData(), 177 methodProbe)); 178 } 179 } 180 181 private boolean isMonitorExitHandler() { 182 if (instructions.size() < pos + 6) { 183 return false; 184 } 185 186 if (!isOpcode(pos, ASTORE)) { 187 return false; 188 } 189 190 if (!isOpcode(pos + 1, ALOAD)) { 191 return false; 192 } 193 194 if (!isOpcode(pos + 2, MONITOREXIT)) { 195 return false; 196 } 197 198 if (!isLabel(pos + 3)) { 199 return false; 200 } 201 202 if (!isOpcode(pos + 4, ALOAD)) { 203 return false; 204 } 205 206 if (!isOpcode(pos + 5, ATHROW)) { 207 return false; 208 } 209 return true; 210 } 211 212 private boolean isLabel(int pos) { 213 return (instructions.get(pos) instanceof LabelNode); 214 } 215 216 private boolean isOpcode(int pos, int opcode) { 217 return (instructions.get(pos) instanceof AbstractInsnNode) 218 && (((AbstractInsnNode) instructions.get(pos)).getOpcode() == opcode); 219 } 220 221 private boolean isExceptionHandler(Label l) { 222 Iterator it = tryCatchBlocks.iterator(); 223 while (it.hasNext()) { 224 TryCatchBlockNode tryCatchBlockNode = ((TryCatchBlockNode) it.next()); 225 if (tryCatchBlockNode.handler.getLabel() == l && 226 (tryCatchBlockNode.type != null)) { 227 return true; 228 } 229 } 230 231 return false; 232 } 233 234 public void visitLdcInsn(final Object cst) { 235 checkFirst(); 236 237 mv.visitLdcInsn(cst); 238 } 239 240 public void visitIincInsn(final int var, final int increment) { 241 checkFirst(); 242 243 mv.visitIincInsn(var, increment); 244 } 245 246 public void visitTableSwitchInsn(final int min, 247 final int max, 248 final Label dflt, 249 final Label labels[]) { 250 checkFirst(); 251 252 addProbe(ProbeFactory.createSelectProbe(getProbeData(), 253 min, max, dflt, labels)); 254 255 mv.visitTableSwitchInsn(min, max, dflt, labels); 256 } 257 258 public void visitLookupSwitchInsn(final Label dflt, 259 final int keys[], 260 final Label labels[]) { 261 checkFirst(); 262 263 addProbe(ProbeFactory.createSelectProbe(getProbeData(), 264 dflt, keys, labels)); 265 266 mv.visitLookupSwitchInsn(dflt, keys, labels); 267 } 268 269 public void visitMultiANewArrayInsn(final String desc, final int dims) { 270 checkFirst(); 271 272 mv.visitMultiANewArrayInsn(desc, dims); 273 } 274 275 public void visitTryCatchBlock(final Label start, final Label end, 276 final Label handler, final String type) { 277 279 mv.visitTryCatchBlock(start, end, handler, type); 280 } 281 282 public void visitTypeInsn(int param, String str) { 283 checkFirst(); 284 285 super.visitTypeInsn(param, str); 286 } 287 288 public void visitAttribute(org.objectweb.asm.Attribute attribute) { 289 checkFirst(); 290 291 super.visitAttribute(attribute); 292 } 293 294 public void visitMaxs(int param, int param1) { 295 297 super.visitMaxs(param, param1); 298 } 299 300 @Override 301 public void visitFrame(int type, int nLocal, Object [] local, int nStack, Object [] stack) { 302 checkFirst(); 303 304 super.visitFrame(type, nLocal, local, nStack, stack); 305 } 306 307 @Override 308 public void visitEnd() { 309 super.visitEnd(); 310 311 if (pos != frames.length) { 312 throw new IllegalStateException ("Inconsistent instrumentation: " 313 + pos + " != " + frames.length); 314 } 315 } 316 317 318 } 319 | Popular Tags |