LabelFlowAnalyzer.java revision 456cb13baa8f60eef812864ed5bbe3c5f858cdbb
1/******************************************************************************* 2 * Copyright (c) 2009, 2011 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.objectweb.asm.AnnotationVisitor; 15import org.objectweb.asm.Attribute; 16import org.objectweb.asm.Label; 17import org.objectweb.asm.MethodVisitor; 18import org.objectweb.asm.Opcodes; 19 20/** 21 * Method visitor to collect flow related information about the {@link Label}s 22 * within a class. It calculates the properties "multitarget" and "successor" 23 * that can afterwards be obtained via {@link LabelInfo}. 24 */ 25public final class LabelFlowAnalyzer implements MethodVisitor { 26 27 /** 28 * <code>true</code> if the current instruction is a potential successor of 29 * the previous instruction. Accessible for testing. 30 */ 31 boolean successor = false; 32 33 /** 34 * <code>true</code> for the very first instruction only. Accessible for 35 * testing. 36 */ 37 boolean first = true; 38 39 public void visitTryCatchBlock(final Label start, final Label end, 40 final Label handler, final String type) { 41 // Enforce probes at the beginning and end of the block: 42 LabelInfo.setTarget(start); 43 LabelInfo.setTarget(handler); 44 } 45 46 public void visitJumpInsn(final int opcode, final Label label) { 47 LabelInfo.setTarget(label); 48 if (opcode == Opcodes.JSR) { 49 throw new AssertionError("Subroutines not supported."); 50 } 51 successor = opcode != Opcodes.GOTO; 52 first = false; 53 } 54 55 public void visitLabel(final Label label) { 56 if (first) { 57 LabelInfo.setTarget(label); 58 } 59 if (successor) { 60 LabelInfo.setSuccessor(label); 61 } 62 } 63 64 public void visitTableSwitchInsn(final int min, final int max, 65 final Label dflt, final Label[] labels) { 66 visitSwitchInsn(dflt, labels); 67 } 68 69 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 70 final Label[] labels) { 71 visitSwitchInsn(dflt, labels); 72 } 73 74 private void visitSwitchInsn(final Label dflt, final Label[] labels) { 75 LabelInfo.resetDone(dflt); 76 LabelInfo.resetDone(labels); 77 setTargetIfNotDone(dflt); 78 for (final Label l : labels) { 79 setTargetIfNotDone(l); 80 } 81 successor = false; 82 first = false; 83 } 84 85 private static void setTargetIfNotDone(final Label label) { 86 if (!LabelInfo.isDone(label)) { 87 LabelInfo.setTarget(label); 88 LabelInfo.setDone(label); 89 } 90 } 91 92 public void visitInsn(final int opcode) { 93 switch (opcode) { 94 case Opcodes.RET: 95 throw new AssertionError("Subroutines not supported."); 96 case Opcodes.IRETURN: 97 case Opcodes.LRETURN: 98 case Opcodes.FRETURN: 99 case Opcodes.DRETURN: 100 case Opcodes.ARETURN: 101 case Opcodes.RETURN: 102 case Opcodes.ATHROW: 103 successor = false; 104 break; 105 default: 106 successor = true; 107 break; 108 } 109 first = false; 110 } 111 112 public void visitIntInsn(final int opcode, final int operand) { 113 successor = true; 114 first = false; 115 } 116 117 public void visitVarInsn(final int opcode, final int var) { 118 successor = true; 119 first = false; 120 } 121 122 public void visitTypeInsn(final int opcode, final String type) { 123 successor = true; 124 first = false; 125 } 126 127 public void visitFieldInsn(final int opcode, final String owner, 128 final String name, final String desc) { 129 successor = true; 130 first = false; 131 } 132 133 public void visitMethodInsn(final int opcode, final String owner, 134 final String name, final String desc) { 135 successor = true; 136 first = false; 137 } 138 139 public void visitLdcInsn(final Object cst) { 140 successor = true; 141 first = false; 142 } 143 144 public void visitIincInsn(final int var, final int increment) { 145 successor = true; 146 first = false; 147 } 148 149 public void visitMultiANewArrayInsn(final String desc, final int dims) { 150 successor = true; 151 first = false; 152 } 153 154 // Not relevant: 155 156 public void visitAttribute(final Attribute attr) { 157 } 158 159 public AnnotationVisitor visitAnnotationDefault() { 160 return null; 161 } 162 163 public AnnotationVisitor visitAnnotation(final String desc, 164 final boolean visible) { 165 return null; 166 } 167 168 public AnnotationVisitor visitParameterAnnotation(final int parameter, 169 final String desc, final boolean visible) { 170 return null; 171 } 172 173 public void visitLocalVariable(final String name, final String desc, 174 final String signature, final Label start, final Label end, 175 final int index) { 176 } 177 178 public void visitCode() { 179 } 180 181 public void visitLineNumber(final int line, final Label start) { 182 } 183 184 public void visitFrame(final int type, final int nLocal, 185 final Object[] local, final int nStack, final Object[] stack) { 186 } 187 188 public void visitMaxs(final int maxStack, final int maxLocals) { 189 } 190 191 public void visitEnd() { 192 } 193 194} 195