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