Only emit the outline positions once for each mapped position
As a side note this also fixes b/284938939 since we emit synthetic outline caller positions after all real positions in the method mapping block.
Bug: b/263357015
Bug: b/284938939
Bug: b/293630963
Bug: b/294904638
Change-Id: I76fac27234be6b231c538109d1cf2e86f5ae7155
diff --git a/src/main/java/com/android/tools/r8/ir/code/Position.java b/src/main/java/com/android/tools/r8/ir/code/Position.java
index b27f447..c7829a5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Position.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Position.java
@@ -274,6 +274,10 @@
public abstract PositionBuilder<?, ?> builderWithCopy();
+ public OutlineCallerPosition asOutlineCaller() {
+ return null;
+ }
+
public abstract static class PositionBuilder<
P extends Position, B extends PositionBuilder<P, B>> {
@@ -608,6 +612,11 @@
}
@Override
+ public OutlineCallerPosition asOutlineCaller() {
+ return this;
+ }
+
+ @Override
public DexMethod getOutlineCallee() {
return outlineCallee;
}
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index 694fe01..7c2c9d6 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.Position.OutlineCallerPosition;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.ClassNaming;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
@@ -56,6 +57,7 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -294,6 +296,8 @@
mappedPositions.sort(Comparator.comparing(MappedPosition::getObfuscatedLine));
+ Map<OutlineCallerPosition, MappedRange> outlineCallerPositions = new LinkedHashMap<>();
+
// Update memberNaming with the collected positions, merging multiple positions into a
// single region whenever possible.
for (int i = 0; i < mappedPositions.size(); /* updated in body */ ) {
@@ -344,44 +348,51 @@
originalRange,
prunedInlinedClasses,
cardinalRangeCache);
+ // firstPosition will contain a potential outline caller.
+ if (firstPosition.isOutlineCaller()) {
+ outlineCallerPositions.putIfAbsent(firstPosition.asOutlineCaller(), lastMappedRange);
+ }
methodSpecificMappingInformation.consume(
info -> lastMappedRange.addMappingInformation(info, Unreachable::raise));
- // firstPosition will contain a potential outline caller.
- if (firstPosition.getOutlineCallee() != null) {
- Int2IntMap positionMap = new Int2IntArrayMap();
- int maxPc = ListUtils.last(mappedPositions).getObfuscatedLine();
- firstPosition
- .getOutlinePositions()
- .forEach(
- (line, position) -> {
- int placeHolderLineToBeFixed;
- if (canUseDexPc) {
- placeHolderLineToBeFixed = maxPc + line + 1;
- } else {
- placeHolderLineToBeFixed =
- positionRemapper.createRemappedPosition(position).getSecond().getLine();
- }
- positionMap.put((int) line, placeHolderLineToBeFixed);
- getMappedRangesForPosition(
- appView,
- getOriginalMethodSignature,
- getBuilder(),
- position,
- residualSignature,
- nonCardinalRangeCache.get(
- placeHolderLineToBeFixed, placeHolderLineToBeFixed),
- nonCardinalRangeCache.get(position.getLine(), position.getLine()),
- prunedInlinedClasses,
- cardinalRangeCache);
- });
- outlinesToFix
- .computeIfAbsent(
- firstPosition.getOutlineCallee(),
- outline -> new OutlineFixupBuilder(computeMappedMethod(outline, appView)))
- .addMappedRangeForOutlineCallee(lastMappedRange, positionMap);
- }
i = j;
}
+ IntBox maxPc = new IntBox(ListUtils.last(mappedPositions).getObfuscatedLine());
+ for (Map.Entry<OutlineCallerPosition, MappedRange> outlinePositionEntry :
+ outlineCallerPositions.entrySet()) {
+ Int2IntMap positionMap = new Int2IntArrayMap();
+ outlinePositionEntry
+ .getKey()
+ .getOutlinePositions()
+ .forEach(
+ (line, position) -> {
+ int placeHolderLineToBeFixed;
+ if (canUseDexPc) {
+ placeHolderLineToBeFixed = maxPc.get() + line + 1;
+ } else {
+ placeHolderLineToBeFixed =
+ positionRemapper.createRemappedPosition(position).getSecond().getLine();
+ }
+ positionMap.put((int) line, placeHolderLineToBeFixed);
+ MappedRange lastRange =
+ getMappedRangesForPosition(
+ appView,
+ getOriginalMethodSignature,
+ getBuilder(),
+ position,
+ residualSignature,
+ nonCardinalRangeCache.get(
+ placeHolderLineToBeFixed, placeHolderLineToBeFixed),
+ nonCardinalRangeCache.get(position.getLine(), position.getLine()),
+ prunedInlinedClasses,
+ cardinalRangeCache);
+ maxPc.set(lastRange.minifiedRange.to);
+ });
+ outlinesToFix
+ .computeIfAbsent(
+ outlinePositionEntry.getKey().getOutlineCallee(),
+ outline -> new OutlineFixupBuilder(computeMappedMethod(outline, appView)))
+ .addMappedRangeForOutlineCallee(outlinePositionEntry.getValue(), positionMap);
+ }
assert mappedPositions.size() <= 1
|| getBuilder().hasNoOverlappingRangesForSignature(residualSignature);
return this;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineMappingInformationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineMappingInformationTest.java
index 362ac40..a51667e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineMappingInformationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineMappingInformationTest.java
@@ -98,9 +98,8 @@
String proguardMap = compileResult.getProguardMap();
if (parameters.isDexRuntime()) {
- // TODO(b/263357015, b/293630963): Outline information is duplicated for pc encoding.
- assertEquals(
- 20, StringUtils.occurrences(proguardMap, "com.android.tools.r8.outlineCallsite"));
+ // TODO(b/263357015, b/293630963): Outline information is not reset for new default events.
+ assertEquals(6, StringUtils.occurrences(proguardMap, "com.android.tools.r8.outlineCallsite"));
} else {
assertEquals(4, StringUtils.occurrences(proguardMap, "com.android.tools.r8.outlineCallsite"));
}