MethodInstrumenter.java
1/*******************************************************************************
2 * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
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 * $Id: $
12 *******************************************************************************/
13package org.jacoco.core.instr;
14
15import org.objectweb.asm.MethodVisitor;
16import org.objectweb.asm.Opcodes;
17import org.objectweb.asm.Type;
18import org.objectweb.asm.commons.GeneratorAdapter;
19
20/**
21 * This method adapter instruments a method to record every block that gets
22 * fully executed.
23 *
24 * @author Marc R. Hoffmann
25 * @version $Revision: $
26 */
27public class MethodInstrumenter extends GeneratorAdapter implements
28 IBlockMethodVisitor {
29
30 private final int methodId;
31
32 private final Type enclosingType;
33
34 private int blockArray;
35
36 /**
37 * Create a new instrumenter instance for the given method.
38 *
39 * @param mv
40 * next method visitor in the chain
41 * @param access
42 * access flags for the method
43 * @param name
44 * name of the method
45 * @param desc
46 * description of the method
47 * @param methodId
48 * unique id of the method within its enclosing type
49 * @param enclosingType
50 * type enclosing this method
51 */
52 public MethodInstrumenter(final MethodVisitor mv, final int access,
53 final String name, final String desc, final int methodId,
54 final Type enclosingType) {
55 super(mv, access, name, desc);
56 this.methodId = methodId;
57 this.enclosingType = enclosingType;
58 }
59
60 @Override
61 public void visitCode() {
62 super.visitCode();
63 // At the very beginning of the method we load the boolean[] array into
64 // a local variable that stores the block coverage of this method.
65
66 push(methodId);
67
68 // Stack[0]: I
69
70 invokeStatic(enclosingType, GeneratorConstants.INIT_METHOD);
71
72 // Stack[0]: [Z
73
74 blockArray = newLocal(GeneratorConstants.BLOCK_ARR);
75 storeLocal(blockArray);
76 }
77
78 @Override
79 public void visitMaxs(final int maxStack, final int maxLocals) {
80 // Max stack size of the probe code is 3
81 super.visitMaxs(maxStack + 3, maxLocals + 1);
82 }
83
84 // === IBlockMethodVisitor ===
85
86 public void visitBlockEndBeforeJump(final int id) {
87 // At the end of every block we set the corresponding position in the
88 // boolean[] array to true.
89
90 loadLocal(blockArray);
91
92 // Stack[0]: [Z
93
94 push(id);
95
96 // Stack[1]: I
97 // Stack[0]: [Z
98
99 push(1);
100
101 // Stack[2]: I
102 // Stack[1]: I
103 // Stack[0]: [Z
104
105 visitInsn(Opcodes.BASTORE);
106 }
107
108 public void visitBlockEnd(final int id) {
109 // nothing to do here
110 }
111
112}