MethodProbesAdapter.java revision 9f4ef8dcffb3acbcd066ec073d87de65eeb06b48
1/******************************************************************************* 2 * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Marc R. Hoffmann - initial API and implementation 10 * 11 *******************************************************************************/ 12package org.jacoco.core.internal.flow; 13 14import org.jacoco.core.JaCoCo; 15import org.objectweb.asm.Label; 16import org.objectweb.asm.MethodVisitor; 17import org.objectweb.asm.Opcodes; 18 19/** 20 * Adapter that creates additional visitor events for probes to be inserted into 21 * a method. 22 */ 23public final class MethodProbesAdapter extends MethodVisitor { 24 25 private final MethodProbesVisitor probesVisitor; 26 27 private final IProbeIdGenerator idGenerator; 28 29 /** 30 * Create a new adapter instance. 31 * 32 * @param probesVisitor 33 * visitor to delegate to 34 * @param idGenerator 35 * generator for unique probe ids 36 */ 37 public MethodProbesAdapter(final MethodProbesVisitor probesVisitor, 38 final IProbeIdGenerator idGenerator) { 39 super(JaCoCo.ASM_API_VERSION, probesVisitor); 40 this.probesVisitor = probesVisitor; 41 this.idGenerator = idGenerator; 42 } 43 44 @Override 45 public void visitLabel(final Label label) { 46 if (LabelInfo.isMultiTarget(label) && LabelInfo.isSuccessor(label)) { 47 probesVisitor.visitProbe(idGenerator.nextId()); 48 } 49 probesVisitor.visitLabel(label); 50 } 51 52 @Override 53 public void visitInsn(final int opcode) { 54 switch (opcode) { 55 case Opcodes.IRETURN: 56 case Opcodes.LRETURN: 57 case Opcodes.FRETURN: 58 case Opcodes.DRETURN: 59 case Opcodes.ARETURN: 60 case Opcodes.RETURN: 61 case Opcodes.ATHROW: 62 probesVisitor.visitInsnWithProbe(opcode, idGenerator.nextId()); 63 break; 64 default: 65 probesVisitor.visitInsn(opcode); 66 break; 67 } 68 } 69 70 @Override 71 public void visitJumpInsn(final int opcode, final Label label) { 72 if (LabelInfo.isMultiTarget(label)) { 73 probesVisitor.visitJumpInsnWithProbe(opcode, label, 74 idGenerator.nextId()); 75 } else { 76 probesVisitor.visitJumpInsn(opcode, label); 77 } 78 } 79 80 @Override 81 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 82 final Label[] labels) { 83 if (markLabels(dflt, labels)) { 84 probesVisitor.visitLookupSwitchInsnWithProbes(dflt, keys, labels); 85 } else { 86 probesVisitor.visitLookupSwitchInsn(dflt, keys, labels); 87 } 88 } 89 90 @Override 91 public void visitTableSwitchInsn(final int min, final int max, 92 final Label dflt, final Label... labels) { 93 if (markLabels(dflt, labels)) { 94 probesVisitor 95 .visitTableSwitchInsnWithProbes(min, max, dflt, labels); 96 } else { 97 probesVisitor.visitTableSwitchInsn(min, max, dflt, labels); 98 } 99 } 100 101 private boolean markLabels(final Label dflt, final Label[] labels) { 102 boolean probe = false; 103 LabelInfo.resetDone(labels); 104 if (LabelInfo.isMultiTarget(dflt)) { 105 LabelInfo.setProbeId(dflt, idGenerator.nextId()); 106 probe = true; 107 } 108 LabelInfo.setDone(dflt); 109 for (final Label l : labels) { 110 if (!LabelInfo.isDone(l) && LabelInfo.isMultiTarget(l)) { 111 LabelInfo.setProbeId(l, idGenerator.nextId()); 112 probe = true; 113 } 114 LabelInfo.setDone(l); 115 } 116 return probe; 117 } 118 119} 120