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 Type enclosingType;
31
32 private int probeArray;
33
34 /**
35 * Create a new instrumenter instance for the given method.
36 *
37 * @param mv
38 * next method visitor in the chain
39 * @param access
40 * access flags for the method
41 * @param name
42 * name of the method
43 * @param desc
44 * description of the method
45 * @param enclosingType
46 * type enclosing this method
47 */
48 public MethodInstrumenter(final MethodVisitor mv, final int access,
49 final String name, final String desc, final Type enclosingType) {
50 super(mv, access, name, desc);
51 this.enclosingType = enclosingType;
52 }
53
54 @Override
55 public void visitCode() {
56 super.visitCode();
57 // At the very beginning of the method we load the boolean[] array into
58 // a local variable that stores the probes for this class.
59 invokeStatic(enclosingType, GeneratorConstants.INIT_METHOD);
60
61 // Stack[0]: [Z
62
63 probeArray = newLocal(GeneratorConstants.PROBEDATA_TYPE);
64 storeLocal(probeArray);
65 }
66
67 @Override
68 public void visitMaxs(final int maxStack, final int maxLocals) {
69 // Max stack size of the probe code is 3
70 super.visitMaxs(maxStack + 3, maxLocals + 1);
71 }
72
73 // === IBlockMethodVisitor ===
74
75 public void visitBlockEndBeforeJump(final int id) {
76 // At the end of every block we set the corresponding position in the
77 // boolean[] array to true.
78
79 loadLocal(probeArray);
80
81 // Stack[0]: [Z
82
83 push(id);
84
85 // Stack[1]: I
86 // Stack[0]: [Z
87
88 push(1);
89
90 // Stack[2]: I
91 // Stack[1]: I
92 // Stack[0]: [Z
93
94 visitInsn(Opcodes.BASTORE);
95 }
96
97 public void visitBlockEnd(final int id) {
98 // nothing to do here
99 }
100
101}