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