• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors
3  * This program and the accompanying materials are made available under
4  * the terms of the Eclipse Public License 2.0 which is available at
5  * http://www.eclipse.org/legal/epl-2.0
6  *
7  * SPDX-License-Identifier: EPL-2.0
8  *
9  * Contributors:
10  *    Marc R. Hoffmann - initial API and implementation
11  *
12  *******************************************************************************/
13 package org.jacoco.core.internal.instr;
14 
15 import org.jacoco.core.internal.flow.ClassProbesAdapter;
16 import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
17 import org.objectweb.asm.ClassReader;
18 import org.objectweb.asm.Opcodes;
19 
20 /**
21  * Factory to find a suitable strategy to access the probe array for a given
22  * class.
23  */
24 public final class ProbeArrayStrategyFactory {
25 
ProbeArrayStrategyFactory()26 	private ProbeArrayStrategyFactory() {
27 	}
28 
29 	/**
30 	 * Creates a suitable strategy instance for the class described by the given
31 	 * reader. Created instance must be used only to process a class or
32 	 * interface for which it has been created and must be used only once.
33 	 *
34 	 * @param classId
35 	 *            class identifier
36 	 * @param reader
37 	 *            reader to get information about the class
38 	 * @param accessorGenerator
39 	 *            accessor to the coverage runtime
40 	 * @return strategy instance
41 	 */
createFor(final long classId, final ClassReader reader, final IExecutionDataAccessorGenerator accessorGenerator)42 	public static IProbeArrayStrategy createFor(final long classId,
43 			final ClassReader reader,
44 			final IExecutionDataAccessorGenerator accessorGenerator) {
45 
46 		final String className = reader.getClassName();
47 		final int version = InstrSupport.getMajorVersion(reader);
48 
49 		if (isInterfaceOrModule(reader)) {
50 			final ProbeCounter counter = getProbeCounter(reader);
51 			if (counter.getCount() == 0) {
52 				return new NoneProbeArrayStrategy();
53 			}
54 // BEGIN android-change
55 			// See https://github.com/jacoco/jacoco/issues/1151
56 			// if (version >= Opcodes.V11 && counter.hasMethods()) {
57 			// 	return new CondyProbeArrayStrategy(className, true, classId,
58 			// 			accessorGenerator);
59 			// }
60 // END android-change
61 			if (version >= Opcodes.V1_8 && counter.hasMethods()) {
62 				return new InterfaceFieldProbeArrayStrategy(className, classId,
63 						counter.getCount(), accessorGenerator);
64 			} else {
65 				return new LocalProbeArrayStrategy(className, classId,
66 						counter.getCount(), accessorGenerator);
67 			}
68 		} else {
69 // BEGIN android-change
70 			// See https://github.com/jacoco/jacoco/issues/1151
71 			// if (version >= Opcodes.V11) {
72 			// 	return new CondyProbeArrayStrategy(className, false, classId,
73 			// 			accessorGenerator);
74 			// }
75 // END android-change
76 			return new ClassFieldProbeArrayStrategy(className, classId,
77 					InstrSupport.needsFrames(version), accessorGenerator);
78 		}
79 	}
80 
isInterfaceOrModule(final ClassReader reader)81 	private static boolean isInterfaceOrModule(final ClassReader reader) {
82 		return (reader.getAccess()
83 				& (Opcodes.ACC_INTERFACE | Opcodes.ACC_MODULE)) != 0;
84 	}
85 
getProbeCounter(final ClassReader reader)86 	private static ProbeCounter getProbeCounter(final ClassReader reader) {
87 		final ProbeCounter counter = new ProbeCounter();
88 		reader.accept(new ClassProbesAdapter(counter, false), 0);
89 		return counter;
90 	}
91 
92 }
93