001: package org.hansel;
002:
003: import static org.objectweb.asm.Opcodes.ALOAD;
004: import static org.objectweb.asm.Opcodes.ASTORE;
005: import static org.objectweb.asm.Opcodes.ATHROW;
006: import static org.objectweb.asm.Opcodes.MONITOREXIT;
007:
008: import java.util.Iterator;
009: import java.util.List;
010: import java.util.Vector;
011:
012: import org.objectweb.asm.Label;
013: import org.objectweb.asm.MethodAdapter;
014: import org.objectweb.asm.MethodVisitor;
015: import org.objectweb.asm.Opcodes;
016: import org.objectweb.asm.tree.AbstractInsnNode;
017: import org.objectweb.asm.tree.InsnList;
018: import org.objectweb.asm.tree.LabelNode;
019: import org.objectweb.asm.tree.LineNumberNode;
020: import org.objectweb.asm.tree.TryCatchBlockNode;
021:
022: public class HanselCodeAdapter extends MethodAdapter {
023: private boolean first;
024: private int pos;
025: private InsnList instructions;
026: private String className;
027: private String methodName;
028: private HanselFrame[] frames;
029: private List<Probe> probes;
030: private List tryCatchBlocks;
031: private Probe methodProbe;
032: private int access;
033: private ClassLoader loader;
034:
035: public HanselCodeAdapter(int access, String className,
036: String methodName, InsnList instructions,
037: List tryCatchBlocks, MethodVisitor mv,
038: HanselFrame[] frames, ClassLoader loader) {
039: super (mv);
040:
041: this .access = access;
042: this .first = true;
043: this .pos = 0;
044: this .instructions = instructions;
045: this .className = className;
046: this .methodName = methodName;
047: this .frames = frames;
048: this .probes = new Vector<Probe>();
049: this .tryCatchBlocks = tryCatchBlocks;
050: this .loader = loader;
051: }
052:
053: private void addProbe(Probe probe) {
054: probe.insertProbeCode(mv);
055: probes.add(probe);
056: }
057:
058: private void checkFirst() {
059: //System.out.println(pos + " -> " + instructions.get(pos) + " : " +
060: // Thread.currentThread().getStackTrace()[3].getMethodName());
061: pos++;
062:
063: if (!first) {
064: return;
065: }
066: first = false;
067:
068: if (!isEmptyPrivateConstructor() && !isStaticConstructor()) {
069: methodProbe = ProbeFactory
070: .createMethodProbe(getProbeData());
071: addProbe(methodProbe);
072: }
073: }
074:
075: private boolean isEmptyPrivateConstructor() {
076: return "<init>".equals(methodName)
077: && ((access & Opcodes.ACC_PRIVATE) > 0)
078: && countRelevantInstructions(instructions) == 3;
079: }
080:
081: private int countRelevantInstructions(InsnList instructions) {
082: int count = 0;
083: for (AbstractInsnNode node : instructions.toArray()) {
084: if (!(node instanceof LineNumberNode)
085: && !(node instanceof LabelNode)) {
086: count++;
087: }
088: }
089: return count;
090: }
091:
092: private boolean isStaticConstructor() {
093: return "<clinit>".equals(methodName);
094: }
095:
096: private ProbeData getProbeData() {
097: return new ProbeData(className, methodName, frames[pos - 1],
098: pos, instructions.size(), loader);
099: }
100:
101: public void visitLineNumber(int line, Label start) {
102: super .visitLineNumber(line, start);
103: checkFirst();
104:
105: int startIndex = Util.findIndex(instructions, start);
106:
107: for (int i = 0; i < probes.size(); i++) {
108: ProbeData pd = probes.get(i).getProbeData();
109: if (startIndex < pd.getPosition()) {
110: pd.setLineNumber(line);
111: }
112: }
113: }
114:
115: public void visitInsn(final int opcode) {
116: checkFirst();
117:
118: mv.visitInsn(opcode);
119: }
120:
121: public void visitIntInsn(final int opcode, final int operand) {
122: checkFirst();
123:
124: mv.visitIntInsn(opcode, operand);
125: }
126:
127: public void visitVarInsn(final int opcode, final int var) {
128: checkFirst();
129:
130: mv.visitVarInsn(opcode, var);
131: }
132:
133: public void visitFieldInsn(final int opcode, final String owner,
134: final String name, final String desc) {
135: checkFirst();
136:
137: mv.visitFieldInsn(opcode, owner, name, desc);
138: }
139:
140: public void visitMethodInsn(final int opcode, final String owner,
141: final String name, final String desc) {
142: checkFirst();
143:
144: mv.visitMethodInsn(opcode, owner, name, desc);
145: }
146:
147: public void visitJumpInsn(final int opcode, final Label label) {
148: checkFirst();
149:
150: if (opcode != Opcodes.GOTO) {
151: addProbe(ProbeFactory.createBranchProbe(getProbeData(),
152: opcode));
153: }
154:
155: mv.visitJumpInsn(opcode, label);
156: }
157:
158: public void visitLabel(final Label label) {
159: //System.out.println(pos + " -> " + instructions.get(pos) + " : visitLabel");
160:
161: pos++;
162:
163: mv.visitLabel(label);
164:
165: if (isExceptionHandler(label) && !isMonitorExitHandler()) {
166: addProbe(ProbeFactory.createExceptionProbe(getProbeData(),
167: methodProbe));
168: }
169: }
170:
171: private boolean isMonitorExitHandler() {
172: if (instructions.size() < pos + 6) {
173: return false;
174: }
175:
176: if (!isOpcode(pos, ASTORE)) {
177: return false;
178: }
179:
180: if (!isOpcode(pos + 1, ALOAD)) {
181: return false;
182: }
183:
184: if (!isOpcode(pos + 2, MONITOREXIT)) {
185: return false;
186: }
187:
188: if (!isLabel(pos + 3)) {
189: return false;
190: }
191:
192: if (!isOpcode(pos + 4, ALOAD)) {
193: return false;
194: }
195:
196: if (!isOpcode(pos + 5, ATHROW)) {
197: return false;
198: }
199: return true;
200: }
201:
202: private boolean isLabel(int pos) {
203: return (instructions.get(pos) instanceof LabelNode);
204: }
205:
206: private boolean isOpcode(int pos, int opcode) {
207: return (instructions.get(pos) instanceof AbstractInsnNode)
208: && (((AbstractInsnNode) instructions.get(pos))
209: .getOpcode() == opcode);
210: }
211:
212: private boolean isExceptionHandler(Label l) {
213: Iterator it = tryCatchBlocks.iterator();
214: while (it.hasNext()) {
215: TryCatchBlockNode tryCatchBlockNode = ((TryCatchBlockNode) it
216: .next());
217: if (tryCatchBlockNode.handler.getLabel() == l
218: && (tryCatchBlockNode.type != null)) {
219: return true;
220: }
221: }
222:
223: return false;
224: }
225:
226: public void visitLdcInsn(final Object cst) {
227: checkFirst();
228:
229: mv.visitLdcInsn(cst);
230: }
231:
232: public void visitIincInsn(final int var, final int increment) {
233: checkFirst();
234:
235: mv.visitIincInsn(var, increment);
236: }
237:
238: public void visitTableSwitchInsn(final int min, final int max,
239: final Label dflt, final Label labels[]) {
240: checkFirst();
241:
242: addProbe(ProbeFactory.createSelectProbe(getProbeData(), min,
243: max, dflt, labels));
244:
245: mv.visitTableSwitchInsn(min, max, dflt, labels);
246: }
247:
248: public void visitLookupSwitchInsn(final Label dflt,
249: final int keys[], final Label labels[]) {
250: checkFirst();
251:
252: addProbe(ProbeFactory.createSelectProbe(getProbeData(), dflt,
253: keys, labels));
254:
255: mv.visitLookupSwitchInsn(dflt, keys, labels);
256: }
257:
258: public void visitMultiANewArrayInsn(final String desc,
259: final int dims) {
260: checkFirst();
261:
262: mv.visitMultiANewArrayInsn(desc, dims);
263: }
264:
265: public void visitTryCatchBlock(final Label start, final Label end,
266: final Label handler, final String type) {
267: //checkFirst();
268:
269: mv.visitTryCatchBlock(start, end, handler, type);
270: }
271:
272: public void visitTypeInsn(int param, String str) {
273: checkFirst();
274:
275: super .visitTypeInsn(param, str);
276: }
277:
278: public void visitAttribute(org.objectweb.asm.Attribute attribute) {
279: checkFirst();
280:
281: super .visitAttribute(attribute);
282: }
283:
284: public void visitMaxs(int param, int param1) {
285: //checkFirst();
286:
287: super .visitMaxs(param, param1);
288: }
289:
290: @Override
291: public void visitFrame(int type, int nLocal, Object[] local,
292: int nStack, Object[] stack) {
293: checkFirst();
294:
295: super .visitFrame(type, nLocal, local, nStack, stack);
296: }
297:
298: @Override
299: public void visitEnd() {
300: super .visitEnd();
301:
302: if (pos != frames.length) {
303: throw new IllegalStateException(
304: "Inconsistent instrumentation: " + pos + " != "
305: + frames.length);
306: }
307: }
308:
309: }
|