Account for inlined frames in outlines
Fixes: 201397823
Fixes: 204643407
Change-Id: Ic4b74d7c3c0dab6461873fb14bfbe5e0a0451d74
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index f49bdd1..16af327 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -534,7 +534,6 @@
lastPosition = currentPosition;
}
}
- Range originalRange = new Range(firstPosition.originalLine, lastPosition.originalLine);
Range obfuscatedRange;
if (method.getCode().isDexCode()
&& method.getCode().asDexCode().getDebugInfo()
@@ -547,34 +546,15 @@
}
ClassNaming.Builder classNamingBuilder = onDemandClassNamingBuilder.get();
MappedRange lastMappedRange =
- classNamingBuilder.addMappedRange(
+ getMappedRangesForPosition(
+ appView.options().dexItemFactory(),
+ getOriginalMethodSignature,
+ classNamingBuilder,
+ firstPosition.method,
+ obfuscatedName,
obfuscatedRange,
- getOriginalMethodSignature.apply(firstPosition.method),
- originalRange,
- obfuscatedName);
- Position caller = firstPosition.caller;
- int inlineFramesCount = 0;
- while (caller != null) {
- inlineFramesCount += 1;
- lastMappedRange =
- classNamingBuilder.addMappedRange(
- obfuscatedRange,
- getOriginalMethodSignature.apply(caller.getMethod()),
- new Range(Math.max(caller.getLine(), 0)), // Prevent against "no-position".
- obfuscatedName);
- if (caller.isRemoveInnerFramesIfThrowingNpe()) {
- lastMappedRange.addMappingInformation(
- RewriteFrameMappingInformation.builder()
- .addCondition(
- ThrowsCondition.create(
- Reference.classFromDescriptor(
- appView.options().dexItemFactory().npeDescriptor.toString())))
- .addRewriteAction(RemoveInnerFramesAction.create(inlineFramesCount))
- .build(),
- Unreachable::raise);
- }
- caller = caller.getCallerPosition();
- }
+ new Range(firstPosition.originalLine, lastPosition.originalLine),
+ firstPosition.caller);
for (MappingInformation info : methodMappingInfo) {
lastMappedRange.addMappingInformation(info, Unreachable::raise);
}
@@ -593,12 +573,15 @@
positionRemapper.createRemappedPosition(position).getSecond().getLine();
}
positionMap.put((int) line, placeHolderLineToBeFixed);
- // TODO(b/204643407): Iterate over caller positions recursively.
- classNamingBuilder.addMappedRange(
+ getMappedRangesForPosition(
+ appView.options().dexItemFactory(),
+ getOriginalMethodSignature,
+ classNamingBuilder,
+ position.getMethod(),
+ obfuscatedName,
new Range(placeHolderLineToBeFixed, placeHolderLineToBeFixed),
- getOriginalMethodSignature.apply(position.getMethod()),
new Range(position.getLine(), position.getLine()),
- obfuscatedName);
+ position.getCallerPosition());
});
outlinesToFix
.computeIfAbsent(
@@ -623,6 +606,45 @@
return classNameMapperBuilder.build();
}
+ private static MappedRange getMappedRangesForPosition(
+ DexItemFactory factory,
+ Function<DexMethod, MethodSignature> getOriginalMethodSignature,
+ Builder classNamingBuilder,
+ DexMethod method,
+ String obfuscatedName,
+ Range obfuscatedRange,
+ Range originalLine,
+ Position caller) {
+ MappedRange lastMappedRange =
+ classNamingBuilder.addMappedRange(
+ obfuscatedRange,
+ getOriginalMethodSignature.apply(method),
+ originalLine,
+ obfuscatedName);
+ int inlineFramesCount = 0;
+ while (caller != null) {
+ inlineFramesCount += 1;
+ lastMappedRange =
+ classNamingBuilder.addMappedRange(
+ obfuscatedRange,
+ getOriginalMethodSignature.apply(caller.getMethod()),
+ new Range(Math.max(caller.getLine(), 0)), // Prevent against "no-position".
+ obfuscatedName);
+ if (caller.isRemoveInnerFramesIfThrowingNpe()) {
+ lastMappedRange.addMappingInformation(
+ RewriteFrameMappingInformation.builder()
+ .addCondition(
+ ThrowsCondition.create(
+ Reference.classFromDescriptor(factory.npeDescriptor.toString())))
+ .addRewriteAction(RemoveInnerFramesAction.create(inlineFramesCount))
+ .build(),
+ Unreachable::raise);
+ }
+ caller = caller.getCallerPosition();
+ }
+ return lastMappedRange;
+ }
+
private static boolean verifyMethodsAreKeptDirectlyOrIndirectly(
AppView<?> appView, List<DexEncodedMethod> methods) {
if (appView.options().isGeneratingClassFiles() || !appView.appInfo().hasClassHierarchy()) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineWithInlineMappingInformationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineWithInlineMappingInformationTest.java
index 6f343e9..fddf01c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineWithInlineMappingInformationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineWithInlineMappingInformationTest.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.optimize.outliner;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoHorizontalClassMerging;
@@ -90,12 +89,7 @@
// and one for
// new ArrayStoreException("Foo")
assertEquals(5, inspector.allClasses().size());
- if (throwInFirstOutline ^ throwOnFirstCall) {
- // TODO(b/204643407): Should always be equal.
- assertNotEquals(expectedStackTrace, stackTrace);
- } else {
- assertEquals(expectedStackTrace, stackTrace);
- }
+ assertEquals(expectedStackTrace, stackTrace);
});
}