1*33edd672SMark// SPDX-License-Identifier: EPL-2.0 and Apache-2.0 2*33edd672SMark// These patches apply to JaCoCo (https://github.com/jacoco/jacoco) and are hereby made available under the terms of the 3*33edd672SMark// Eclipse Public License 2.0 available at: 4*33edd672SMark// http://www.eclipse.org/legal/epl-2.0 5*33edd672SMarkdiff --git org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java 6*33edd672SMarkindex 476c9e34..bc192dc6 100644 7*33edd672SMark--- org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java 8*33edd672SMark+++ org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java 9*33edd672SMark@@ -24,6 +24,7 @@ import org.objectweb.asm.MethodVisitor; 10*33edd672SMark public class ClassInstrumenter extends ClassProbesVisitor { 11*33edd672SMark 12*33edd672SMark private final IProbeArrayStrategy probeArrayStrategy; 13*33edd672SMark+ private final IProbeInserterFactory probeInserterFactory; 14*33edd672SMark 15*33edd672SMark private String className; 16*33edd672SMark 17*33edd672SMark@@ -40,6 +41,22 @@ public class ClassInstrumenter extends ClassProbesVisitor { 18*33edd672SMark final ClassVisitor cv) { 19*33edd672SMark super(cv); 20*33edd672SMark this.probeArrayStrategy = probeArrayStrategy; 21*33edd672SMark+ this.probeInserterFactory = new IProbeInserterFactory() { 22*33edd672SMark+ @Override 23*33edd672SMark+ public ProbeInserter makeProbeInserter(int access, String name, 24*33edd672SMark+ String desc, MethodVisitor mv, 25*33edd672SMark+ IProbeArrayStrategy arrayStrategy) { 26*33edd672SMark+ return new ProbeInserter(access, name, desc, mv, arrayStrategy); 27*33edd672SMark+ } 28*33edd672SMark+ }; 29*33edd672SMark+ } 30*33edd672SMark+ 31*33edd672SMark+ public ClassInstrumenter(final IProbeArrayStrategy probeArrayStrategy, 32*33edd672SMark+ final IProbeInserterFactory probeInserterFactory, 33*33edd672SMark+ final ClassVisitor cv) { 34*33edd672SMark+ super(cv); 35*33edd672SMark+ this.probeArrayStrategy = probeArrayStrategy; 36*33edd672SMark+ this.probeInserterFactory = probeInserterFactory; 37*33edd672SMark } 38*33edd672SMark 39*33edd672SMark @Override 40*33edd672SMark@@ -71,8 +88,9 @@ public class ClassInstrumenter extends ClassProbesVisitor { 41*33edd672SMark return null; 42*33edd672SMark } 43*33edd672SMark final MethodVisitor frameEliminator = new DuplicateFrameEliminator(mv); 44*33edd672SMark- final ProbeInserter probeVariableInserter = new ProbeInserter(access, 45*33edd672SMark- name, desc, frameEliminator, probeArrayStrategy); 46*33edd672SMark+ final ProbeInserter probeVariableInserter = 47*33edd672SMark+ probeInserterFactory.makeProbeInserter(access, name, desc, 48*33edd672SMark+ frameEliminator, probeArrayStrategy); 49*33edd672SMark return new MethodInstrumenter(probeVariableInserter, 50*33edd672SMark probeVariableInserter); 51*33edd672SMark } 52*33edd672SMarkdiff --git org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserterFactory.java org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserterFactory.java 53*33edd672SMarknew file mode 100644 54*33edd672SMarkindex 00000000..19c2a7e2 55*33edd672SMark--- /dev/null 56*33edd672SMark+++ org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserterFactory.java 57*33edd672SMark@@ -0,0 +1,8 @@ 58*33edd672SMark+package org.jacoco.core.internal.instr; 59*33edd672SMark+ 60*33edd672SMark+import org.objectweb.asm.MethodVisitor; 61*33edd672SMark+ 62*33edd672SMark+public interface IProbeInserterFactory { 63*33edd672SMark+ ProbeInserter makeProbeInserter(int access, String name, String desc, 64*33edd672SMark+ MethodVisitor mv, IProbeArrayStrategy arrayStrategy); 65*33edd672SMark+} 66*33edd672SMarkdiff --git org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java 67*33edd672SMarkindex 0f5b99ff..80965dfe 100644 68*33edd672SMark--- org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java 69*33edd672SMark+++ org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java 70*33edd672SMark@@ -25,7 +25,7 @@ import org.objectweb.asm.TypePath; 71*33edd672SMark * addition the probe array has to be retrieved at the beginning of the method 72*33edd672SMark * and stored in a local variable. 73*33edd672SMark */ 74*33edd672SMark-class ProbeInserter extends MethodVisitor implements IProbeInserter { 75*33edd672SMark+public class ProbeInserter extends MethodVisitor implements IProbeInserter { 76*33edd672SMark 77*33edd672SMark private final IProbeArrayStrategy arrayStrategy; 78*33edd672SMark 79*33edd672SMark@@ -36,7 +36,7 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter { 80*33edd672SMark private final boolean clinit; 81*33edd672SMark 82*33edd672SMark /** Position of the inserted variable. */ 83*33edd672SMark- private final int variable; 84*33edd672SMark+ protected final int variable; 85*33edd672SMark 86*33edd672SMark /** Label for the new beginning of the method */ 87*33edd672SMark private final Label beginLabel; 88*33edd672SMark@@ -56,7 +56,7 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter { 89*33edd672SMark * callback to create the code that retrieves the reference to 90*33edd672SMark * the probe array 91*33edd672SMark */ 92*33edd672SMark- ProbeInserter(final int access, final String name, final String desc, 93*33edd672SMark+ public ProbeInserter(final int access, final String name, final String desc, 94*33edd672SMark final MethodVisitor mv, final IProbeArrayStrategy arrayStrategy) { 95*33edd672SMark super(InstrSupport.ASM_API_VERSION, mv); 96*33edd672SMark this.clinit = InstrSupport.CLINIT_NAME.equals(name); 97*33edd672SMark@@ -91,6 +91,10 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter { 98*33edd672SMark mv.visitInsn(Opcodes.BASTORE); 99*33edd672SMark } 100*33edd672SMark 101*33edd672SMark+ protected Object getLocalVariableType() { 102*33edd672SMark+ return InstrSupport.DATAFIELD_DESC; 103*33edd672SMark+ } 104*33edd672SMark+ 105*33edd672SMark @Override 106*33edd672SMark public void visitCode() { 107*33edd672SMark mv.visitLabel(beginLabel); 108*33edd672SMark@@ -118,6 +122,10 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter { 109*33edd672SMark public AnnotationVisitor visitLocalVariableAnnotation(final int typeRef, 110*33edd672SMark final TypePath typePath, final Label[] start, final Label[] end, 111*33edd672SMark final int[] index, final String descriptor, final boolean visible) { 112*33edd672SMark+ if (getLocalVariableType() == null) { 113*33edd672SMark+ return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); 114*33edd672SMark+ } 115*33edd672SMark+ 116*33edd672SMark final int[] newIndex = new int[index.length]; 117*33edd672SMark for (int i = 0; i < newIndex.length; i++) { 118*33edd672SMark newIndex[i] = map(index[i]); 119*33edd672SMark@@ -137,6 +145,9 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter { 120*33edd672SMark } 121*33edd672SMark 122*33edd672SMark private int map(final int var) { 123*33edd672SMark+ if (getLocalVariableType() == null) { 124*33edd672SMark+ return var; 125*33edd672SMark+ } 126*33edd672SMark if (var < variable) { 127*33edd672SMark return var; 128*33edd672SMark } else { 129*33edd672SMark@@ -153,13 +164,18 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter { 130*33edd672SMark "ClassReader.accept() should be called with EXPAND_FRAMES flag"); 131*33edd672SMark } 132*33edd672SMark 133*33edd672SMark+ if (getLocalVariableType() == null) { 134*33edd672SMark+ mv.visitFrame(type, nLocal, local, nStack, stack); 135*33edd672SMark+ return; 136*33edd672SMark+ } 137*33edd672SMark+ 138*33edd672SMark final Object[] newLocal = new Object[Math.max(nLocal, variable) + 1]; 139*33edd672SMark int idx = 0; // Arrays index for existing locals 140*33edd672SMark int newIdx = 0; // Array index for new locals 141*33edd672SMark int pos = 0; // Current variable position 142*33edd672SMark while (idx < nLocal || pos <= variable) { 143*33edd672SMark if (pos == variable) { 144*33edd672SMark- newLocal[newIdx++] = InstrSupport.DATAFIELD_DESC; 145*33edd672SMark+ newLocal[newIdx++] = getLocalVariableType(); 146*33edd672SMark pos++; 147*33edd672SMark } else { 148*33edd672SMark if (idx < nLocal) { 149