Reapply "Reapply "Represent all original method information in positions""
This reverts commit 65675a38bfbebd533327612ffc69020de4195c21.
Bug: b/261971803
Change-Id: Iec9c78c182b3f2cdaa39104fd7773dff5aff2f32
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 79623e1..9964d6e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -17,10 +17,8 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppServices;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
@@ -28,7 +26,6 @@
import com.android.tools.r8.graph.GenericSignatureContextBuilder;
import com.android.tools.r8.graph.GenericSignatureCorrectnessHelper;
import com.android.tools.r8.graph.ProgramDefinition;
-import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.analysis.ClassInitializerAssertionEnablingAnalysis;
@@ -780,8 +777,6 @@
}
appView.appInfo().notifyMinifierFinished();
- assert verifyMovedMethodsHaveOriginalMethodPosition(appView, getDirectApp(appView));
-
// If a method filter is present don't produce output since the application is likely partial.
if (options.hasMethodsFilter()) {
System.out.println("Finished compilation with method filter: ");
@@ -841,6 +836,8 @@
options.androidResourceProvider, options.androidResourceConsumer, appView.reporter());
}
+ assert appView.verifyMovedMethodsHaveOriginalMethodPosition();
+
// Generate the resulting application resources.
writeApplication(appView, inputApp, executorService);
@@ -946,57 +943,6 @@
executorService);
}
- @SuppressWarnings("ReferenceEquality")
- private static boolean verifyMovedMethodsHaveOriginalMethodPosition(
- AppView<?> appView, DirectMappedDexApplication application) {
- application
- .classesWithDeterministicOrder()
- .forEach(
- clazz ->
- clazz.forEachProgramMethod(
- method -> {
- DexMethod originalMethod =
- appView.graphLens().getOriginalMethodSignature(method.getReference());
- if (originalMethod != method.getReference()) {
- DexEncodedMethod definition = method.getDefinition();
- Code code = definition.getCode();
- if (code == null) {
- return;
- }
- if (code.isCfCode() || code.isDexCode()) {
- assert verifyOriginalMethodInPosition(code, originalMethod, method);
- } else {
- assert code.isDefaultInstanceInitializerCode() || code.isThrowNullCode();
- }
- }
- }));
- return true;
- }
-
- @SuppressWarnings({"ComplexBooleanConstant", "ReferenceEquality"})
- private static boolean verifyOriginalMethodInPosition(
- Code code, DexMethod originalMethod, ProgramMethod context) {
- code.forEachPosition(
- originalMethod,
- position -> {
- if (position.isOutlineCaller()) {
- // Check the outlined positions for the original method
- position
- .getOutlinePositions()
- .forEach(
- (ignored, outlinePosition) -> {
- assert outlinePosition.hasMethodInChain(originalMethod);
- });
- } else if (context.getDefinition().isD8R8Synthesized()) {
- // TODO(b/261971803): Enable assert.
- assert true || position.hasMethodInChain(originalMethod);
- } else {
- assert position.getOutermostCaller().getMethod() == originalMethod;
- }
- });
- return true;
- }
-
private AppView<AppInfoWithLiveness> runEnqueuer(
AnnotationRemover.Builder annotationRemoverBuilder,
ExecutorService executorService,
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index a5fe760..3863b30 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -975,6 +975,7 @@
throws ExecutionException {
rewriteWithLensAndApplication(
lens, application, executorService, timing, withClassHierarchy(), lens.getPrevious());
+ assert verifyMovedMethodsHaveOriginalMethodPosition();
}
private static void rewriteWithLensAndApplication(
@@ -1283,4 +1284,33 @@
public String getPrunedClassSourceFileInfo(DexType dexType) {
return sourceFileForPrunedTypes.get(dexType);
}
+
+ public boolean verifyMovedMethodsHaveOriginalMethodPosition() {
+ DirectMappedDexApplication application = app().asDirect();
+ application
+ .classesWithDeterministicOrder()
+ .forEach(
+ clazz ->
+ clazz.forEachProgramMethod(
+ method -> {
+ assert verifyOriginalMethodInPosition(method);
+ }));
+ return true;
+ }
+
+ private static boolean verifyOriginalMethodInPosition(ProgramMethod context) {
+ Code code = context.getDefinition().getCode();
+ if (code == null) {
+ return true;
+ }
+ DexMethod thisMethod = context.getReference();
+ code.forEachPosition(
+ context.getReference(),
+ context.getDefinition().isD8R8Synthesized(),
+ position -> {
+ DexMethod outerCaller = position.getOutermostCaller().getMethod();
+ assert thisMethod.isIdenticalTo(outerCaller);
+ });
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index b636a5c..bc71dd6 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -684,7 +684,6 @@
this,
localVariables,
method,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
callerPosition,
origin,
appView);
@@ -893,8 +892,17 @@
@Override
public Code getCodeAsInlining(
- DexMethod caller, DexMethod callee, DexItemFactory factory, boolean isCalleeD8R8Synthesized) {
- Position callerPosition = SyntheticPosition.builder().setLine(0).setMethod(caller).build();
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ Position callerPosition =
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(caller)
+ .setIsD8R8Synthesized(isCallerD8R8Synthesized)
+ .build();
List<CfInstruction> newInstructions = new ArrayList<>(instructions.size() + 2);
CfLabel firstLabel;
if (instructions.get(0).isLabel()) {
@@ -968,7 +976,8 @@
}
@Override
- public void forEachPosition(DexMethod method, Consumer<Position> positionConsumer) {
+ public void forEachPosition(
+ DexMethod method, boolean isD8R8Synthesized, Consumer<Position> positionConsumer) {
for (CfInstruction instruction : getInstructions()) {
if (instruction.isPosition()) {
positionConsumer.accept(instruction.asPosition().getPosition());
diff --git a/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java b/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
index 59788bc..0670aeb 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
@@ -16,10 +16,7 @@
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(
- method.getOrigin(),
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- sb.toString());
+ return new CfCodeDiagnostics(method.getOrigin(), method.getReference(), sb.toString());
}
public static CfCodeDiagnostics multipleFramesForLabel(ProgramMethod method, AppView<?> appView) {
@@ -27,10 +24,7 @@
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(
- method.getOrigin(),
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- sb.toString());
+ return new CfCodeDiagnostics(method.getOrigin(), method.getReference(), sb.toString());
}
public static CfCodeDiagnostics noFramesForMethodWithJumps(
@@ -40,10 +34,7 @@
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(
- method.getOrigin(),
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- sb.toString());
+ return new CfCodeDiagnostics(method.getOrigin(), method.getReference(), sb.toString());
}
public static CfCodeDiagnostics invalidTryCatchRange(
@@ -57,10 +48,7 @@
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(
- method.getOrigin(),
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- sb.toString());
+ return new CfCodeDiagnostics(method.getOrigin(), method.getReference(), sb.toString());
}
public static CfCodeDiagnostics invalidStackMapForInstruction(
@@ -80,9 +68,6 @@
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(
- method.getOrigin(),
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- sb.toString());
+ return new CfCodeDiagnostics(method.getOrigin(), method.getReference(), sb.toString());
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 566f79e..36d8464 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -191,55 +191,53 @@
return true;
}
- public Code getCodeAsInlining(DexMethod caller, DexEncodedMethod callee, DexItemFactory factory) {
- return getCodeAsInlining(caller, callee.getReference(), factory, callee.isD8R8Synthesized());
- }
-
public Code getCodeAsInlining(
- DexMethod caller, DexMethod callee, DexItemFactory factory, boolean isCalleeD8R8Synthesized) {
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
throw new Unreachable();
}
public static Position newInlineePosition(
- Position callerPosition, Position oldPosition, boolean isCalleeD8R8Synthesized) {
- Position outermostCaller = oldPosition.getOutermostCaller();
+ Position callerPosition, Position calleePosition, boolean isCalleeD8R8Synthesized) {
+ Position outermostCallee = calleePosition.getOutermostCaller();
+ // If the callee is not synthetic, then just append the frame.
+ assert outermostCallee.isD8R8Synthesized() == isCalleeD8R8Synthesized;
if (!isCalleeD8R8Synthesized) {
- return removeSameMethodAndLineZero(oldPosition, callerPosition);
+ assert !outermostCallee.isOutline();
+ return calleePosition.withOutermostCallerPosition(callerPosition);
}
// We can replace the position since the callee was synthesized by the compiler, however, if
// the position carries special information we need to copy it.
- if (!outermostCaller.isOutline() && !outermostCaller.isRemoveInnerFramesIfThrowingNpe()) {
- return oldPosition.replacePosition(outermostCaller, callerPosition);
+ if (!outermostCallee.isOutline() && !outermostCallee.isRemoveInnerFramesIfThrowingNpe()) {
+ return calleePosition.replacePosition(outermostCallee, callerPosition);
}
+
assert !callerPosition.isOutline();
- PositionBuilder<?, ?> positionBuilder =
- outermostCaller
- .builderWithCopy()
- .setMethod(callerPosition.getMethod())
- .setLine(callerPosition.getLine());
+ assert !callerPosition.hasCallerPosition();
+ // Copy the callee frame to ensure transfer of the outline key if present.
+ PositionBuilder<?, ?> newCallerBuilder =
+ outermostCallee.builderWithCopy().setMethod(callerPosition.getMethod());
+ // If the callee is an outline, the line must be that of the outline to maintain the positions.
+ if (outermostCallee.isOutline()) {
+ // This does not implement inlining an outline. The cases this hits should always be a full
+ // "move as inlining" to be correct.
+ assert callerPosition.isD8R8Synthesized();
+ assert callerPosition.getLine() == 0;
+ } else {
+ newCallerBuilder.setLine(outermostCallee.getLine());
+ }
+ // Transfer other info from the caller.
if (callerPosition.isRemoveInnerFramesIfThrowingNpe()) {
- positionBuilder.setRemoveInnerFramesIfThrowingNpe(true);
+ newCallerBuilder.setRemoveInnerFramesIfThrowingNpe(true);
}
- return oldPosition.replacePosition(outermostCaller, positionBuilder.build());
+ return calleePosition.replacePosition(outermostCallee, newCallerBuilder.build());
}
- @Deprecated()
- @SuppressWarnings("ReferenceEquality")
- // TODO(b/261971803): When having complete control over the positions we should not need this.
- private static Position removeSameMethodAndLineZero(
- Position calleePosition, Position callerPosition) {
- Position outermostCaller = calleePosition.getOutermostCaller();
- if (outermostCaller.getLine() == 0) {
- while (callerPosition != null
- && outermostCaller.getMethod() == callerPosition.getMethod()
- && callerPosition.getLine() == 0) {
- callerPosition = callerPosition.getCallerPosition();
- }
- }
- return calleePosition.withOutermostCallerPosition(callerPosition);
- }
-
- public void forEachPosition(DexMethod method, Consumer<Position> positionConsumer) {
+ public void forEachPosition(
+ DexMethod method, boolean isD8R8Synthesized, Consumer<Position> positionConsumer) {
// Intentionally empty. Override where we have fully build CF or DEX code.
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
index b70ff11..906a0be 100644
--- a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.graph.lens.MethodLookupResult;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SyntheticPosition;
@@ -87,6 +88,19 @@
method.setCode(get().toCfCode(method, appView.dexItemFactory(), superType), appView);
}
+ @Override
+ public Code getCodeAsInlining(
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ // TODO(b/261971803): It is odd this code does not have an original position for the <init>.
+ // See OverrideParentCollisionTest for a case hitting this inlining where callee is a
+ // non-synthetic non-default <init> (it has argument String).
+ return this;
+ }
+
@SuppressWarnings("ReferenceEquality")
private static boolean hasDefaultInstanceInitializerCode(
ProgramMethod method, AppView<?> appView) {
@@ -144,10 +158,9 @@
AppView<?> appView,
Origin origin,
MutableMethodConversionOptions conversionOptions) {
- DexMethod originalMethod =
- appView.graphLens().getOriginalMethodSignature(method.getReference());
DefaultInstanceInitializerSourceCode source =
- new DefaultInstanceInitializerSourceCode(originalMethod);
+ new DefaultInstanceInitializerSourceCode(
+ method.getReference(), method.getDefinition().isD8R8Synthesized());
return IRBuilder.create(method, appView, source, origin).build(method, conversionOptions);
}
@@ -161,10 +174,9 @@
Position callerPosition,
Origin origin,
RewrittenPrototypeDescription protoChanges) {
- DexMethod originalMethod =
- appView.graphLens().getOriginalMethodSignature(method.getReference());
DefaultInstanceInitializerSourceCode source =
- new DefaultInstanceInitializerSourceCode(originalMethod, callerPosition);
+ new DefaultInstanceInitializerSourceCode(
+ method.getReference(), method.getDefinition().isD8R8Synthesized(), callerPosition);
return IRBuilder.createForInlining(
method, appView, codeLens, source, origin, valueNumberGenerator, protoChanges)
.build(context, MethodConversionOptions.nonConverting());
@@ -410,25 +422,33 @@
static class DefaultInstanceInitializerSourceCode extends SyntheticStraightLineSourceCode {
- DefaultInstanceInitializerSourceCode(DexMethod method) {
- this(method, null);
+ DefaultInstanceInitializerSourceCode(DexMethod method, boolean isD8R8Synthesized) {
+ this(method, isD8R8Synthesized, null);
}
- DefaultInstanceInitializerSourceCode(DexMethod method, Position callerPosition) {
- super(
- getInstructionBuilders(),
+ DefaultInstanceInitializerSourceCode(
+ DexMethod method, boolean isD8R8Synthesized, Position callerPosition) {
+ super(getInstructionBuilders(), getPosition(method, isD8R8Synthesized, callerPosition));
+ }
+
+ private static Position getPosition(
+ DexMethod method, boolean isD8R8Synthesized, Position callerPosition) {
+ SyntheticPosition calleePosition =
SyntheticPosition.builder()
.setLine(0)
.setMethod(method)
- .setCallerPosition(callerPosition)
- .build());
+ .setIsD8R8Synthesized(isD8R8Synthesized)
+ .build();
+ return callerPosition == null
+ ? calleePosition
+ : Code.newInlineePosition(callerPosition, calleePosition, isD8R8Synthesized);
}
private static List<Consumer<IRBuilder>> getInstructionBuilders() {
return ImmutableList.of(
builder ->
builder.add(
- com.android.tools.r8.ir.code.InvokeDirect.builder()
+ InvokeDirect.builder()
.setMethod(
getParentConstructor(
builder.getProgramMethod(), builder.dexItemFactory()))
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index f3fd961..e800b21 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -351,7 +351,11 @@
@Override
public Code getCodeAsInlining(
- DexMethod caller, DexMethod callee, DexItemFactory factory, boolean isCalleeD8R8Synthesized) {
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
return new DexCode(
registerSize,
incomingRegisterSize,
@@ -396,7 +400,8 @@
// => Insert a default event and potentially advance line.
// 4) There is no SET_POSITION_FRAME and no default event setting a position for PC 0..
// => Insert a SET_POSITION_FRAME and a default event and potentially advance line.
- PositionInfo positionInfo = computePreamblePosition(callee, eventBasedInfo);
+ PositionInfo positionInfo =
+ computePreamblePosition(callee, isCalleeD8R8Synthesized, eventBasedInfo);
DexDebugEvent[] oldEvents = eventBasedInfo.events;
boolean adjustStartPosition =
!positionInfo.hasLinePositionAtPcZero() && debugInfo.getStartLine() > 0;
@@ -537,7 +542,6 @@
new DexSourceCode(
this,
method,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
null,
appView.dexItemFactory());
return IRBuilder.create(method, appView, source, origin).build(method, conversionOptions);
@@ -558,7 +562,6 @@
new DexSourceCode(
this,
method,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
callerPosition,
appView.dexItemFactory());
return IRBuilder.createForInlining(
@@ -875,7 +878,8 @@
}
@Override
- public void forEachPosition(DexMethod method, Consumer<Position> positionConsumer) {
+ public void forEachPosition(
+ DexMethod method, boolean isD8R8Synthesized, Consumer<Position> positionConsumer) {
if (getDebugInfo() == null || getDebugInfo().isPcBasedInfo()) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
index e323ab8..e5ca60d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
@@ -57,9 +57,9 @@
private List<DexDebugEntry> entries = new ArrayList<>();
private final DexDebugPositionState positionState;
- public DexDebugEntryBuilder(int startLine, DexMethod method) {
+ public DexDebugEntryBuilder(DexMethod method, boolean isD8R8Synthesized, int startLine) {
assert method != null;
- positionState = new DexDebugPositionState(startLine, method);
+ positionState = new DexDebugPositionState(startLine, method, isD8R8Synthesized);
}
public DexDebugEntryBuilder(DexEncodedMethod method, DexItemFactory factory) {
@@ -68,7 +68,9 @@
EventBasedDebugInfo info = code.getDebugInfo().asEventBasedInfo();
// Only event based debug info supports conversion to entries.
assert info != null;
- positionState = new DexDebugPositionState(info.startLine, method.getReference());
+ positionState =
+ new DexDebugPositionState(
+ info.startLine, method.getReference(), method.isD8R8Synthesized());
int argumentRegister = code.registerSize - code.incomingRegisterSize;
if (!method.accessFlags.isStatic()) {
DexString name = factory.thisName;
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index b77b311..557bb44 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -202,10 +202,12 @@
return;
}
startLine = position.getLine();
+ Position outermostCaller = position.getOutermostCaller();
emittedPosition =
SourcePosition.builder()
.setLine(position.getLine())
- .setMethod(position.getOutermostCaller().getMethod())
+ .setMethod(outermostCaller.getMethod())
+ .setIsD8R8Synthesized(outermostCaller.isD8R8Synthesized())
.build();
}
assert emittedPc != pc;
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
index 1a0023a..3707fdf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -239,8 +239,8 @@
return parameters.length;
}
- public List<DexDebugEntry> computeEntries(DexMethod method) {
- DexDebugEntryBuilder builder = new DexDebugEntryBuilder(startLine, method);
+ public List<DexDebugEntry> computeEntries(DexMethod method, boolean isD8R8Synthesized) {
+ DexDebugEntryBuilder builder = new DexDebugEntryBuilder(method, isD8R8Synthesized, startLine);
for (DexDebugEvent event : events) {
event.accept(builder);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java b/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java
index 96eb206..26f1577 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java
@@ -27,11 +27,13 @@
private int currentPc = 0;
private int currentLine;
protected DexMethod currentMethod;
+ protected boolean isCurrentMethodD8R8Synthesized;
protected Position currentPosition;
- public DexDebugPositionState(int startLine, DexMethod method) {
+ public DexDebugPositionState(int startLine, DexMethod method, boolean isD8R8Synthesized) {
currentLine = startLine;
currentMethod = method;
+ isCurrentMethodD8R8Synthesized = isD8R8Synthesized;
}
@Override
@@ -50,6 +52,7 @@
assert setPositionFrame.getPosition() != null;
Position position = setPositionFrame.getPosition();
currentMethod = position.getMethod();
+ isCurrentMethodD8R8Synthesized = position.isD8R8Synthesized();
currentPosition = position;
}
@@ -103,6 +106,7 @@
return (getCurrentLine() > 0 ? SourcePosition.builder() : SyntheticPosition.builder())
.setLine(getCurrentLine())
.setMethod(currentMethod)
+ .setIsD8R8Synthesized(isCurrentMethodD8R8Synthesized)
.build();
} else {
return currentPosition.builderWithCopy().setLine(getCurrentLine()).build();
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 87740a8..c1f8ac7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -213,11 +213,12 @@
/**
* Flags this method as no longer being obsolete.
*
- * Example use case: The vertical class merger optimistically merges two classes before it is
+ * <p>Example use case: The vertical class merger optimistically merges two classes before it is
* guaranteed that the two classes can be merged. In this process, methods are moved from the
- * source class to the target class using {@link #toTypeSubstitutedMethod(DexMethod)}, which
- * causes the original methods of the source class to become obsolete. If vertical class merging
- * is aborted, the original methods of the source class needs to be marked as not being obsolete.
+ * source class to the target class using {@link #toTypeSubstitutedMethodAsInlining(DexMethod,
+ * DexItemFactory)}, which causes the original methods of the source class to become obsolete. If
+ * vertical class merging is aborted, the original methods of the source class needs to be marked
+ * as not being obsolete.
*/
public void unsetObsolete() {
obsolete = false;
@@ -1124,16 +1125,6 @@
return new CfCode(getReference().holder, 3, locals, instructionBuilder.build());
}
- public DexEncodedMethod toTypeSubstitutedMethod(DexMethod method) {
- checkIfObsolete();
- return toTypeSubstitutedMethodHelper(method, isD8R8Synthesized(), null);
- }
-
- public DexEncodedMethod toTypeSubstitutedMethod(DexMethod method, Consumer<Builder> consumer) {
- checkIfObsolete();
- return toTypeSubstitutedMethodHelper(method, isD8R8Synthesized(), consumer);
- }
-
public DexEncodedMethod toTypeSubstitutedMethodAsInlining(
DexMethod method, DexItemFactory factory) {
checkIfObsolete();
@@ -1142,12 +1133,20 @@
public DexEncodedMethod toTypeSubstitutedMethodAsInlining(
DexMethod method, DexItemFactory factory, Consumer<Builder> consumer) {
+ boolean isCallerD8R8Synthesized = true;
return toTypeSubstitutedMethodHelper(
method,
- true,
+ isCallerD8R8Synthesized,
builder -> {
if (code != null) {
- builder.setCode(getCode().getCodeAsInlining(method, this, factory));
+ builder.setCode(
+ getCode()
+ .getCodeAsInlining(
+ method,
+ isCallerD8R8Synthesized,
+ getReference(),
+ isD8R8Synthesized(),
+ factory));
}
if (consumer != null) {
consumer.accept(builder);
@@ -1181,24 +1180,26 @@
return builder.build();
}
- @SuppressWarnings("ReferenceEquality")
- public ProgramMethod toPrivateSyntheticMethod(DexProgramClass holder, DexMethod method) {
+ public ProgramMethod toPrivateSyntheticMethod(
+ DexProgramClass holder, DexMethod method, DexItemFactory factory) {
assert !isStatic();
assert !isPrivate();
- assert getHolderType() == method.getHolderType();
+ assert getHolderType().isIdenticalTo(method.getHolderType());
checkIfObsolete();
- return new ProgramMethod(
- holder,
- syntheticBuilder(this)
- .setMethod(method)
- .modifyAccessFlags(
- accessFlags -> {
- accessFlags.setSynthetic();
- accessFlags.unsetProtected();
- accessFlags.unsetPublic();
- accessFlags.setPrivate();
- })
- .build());
+ DexEncodedMethod newMethod =
+ toTypeSubstitutedMethodAsInlining(
+ method,
+ factory,
+ builder -> {
+ builder.modifyAccessFlags(
+ accessFlags -> {
+ accessFlags.setSynthetic();
+ accessFlags.unsetProtected();
+ accessFlags.unsetPublic();
+ accessFlags.setPrivate();
+ });
+ });
+ return new ProgramMethod(holder, newMethod);
}
public DexEncodedMethod toForwardingMethod(DexClass newHolder, AppView<?> definitions) {
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index 5676a96..c7fe5c9 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -181,8 +181,15 @@
}
@Override
- public Code getCodeAsInlining(DexMethod caller, DexEncodedMethod callee, DexItemFactory factory) {
- return asCfCode().getCodeAsInlining(caller, callee, factory);
+ public Code getCodeAsInlining(
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ return asCfCode()
+ .getCodeAsInlining(
+ caller, isCallerD8R8Synthesized, callee, isCalleeD8R8Synthesized, factory);
}
public static class DebugParsingOptions {
diff --git a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
index 735be28..a58f744 100644
--- a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
+++ b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
@@ -55,6 +55,18 @@
}
@Override
+ public Code getCodeAsInlining(
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ // We don't maintain a position on the throwing stub. We may want to reconsider this as it
+ // would allow retracing to recover inlinings of this stub.
+ return this;
+ }
+
+ @Override
public IRCode buildIR(
ProgramMethod method,
AppView<?> appView,
@@ -131,7 +143,7 @@
@Override
public TryHandler[] getHandlers() {
- return new TryHandler[0];
+ return TryHandler.EMPTY_ARRAY;
}
@Override
@@ -164,7 +176,7 @@
@Override
public Try[] getTries() {
- return new Try[0];
+ return Try.EMPTY_ARRAY;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java b/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java
index 908749c..4810b23 100644
--- a/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java
+++ b/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java
@@ -258,12 +258,12 @@
}
/** Fixup a method definition. */
- @SuppressWarnings("ReferenceEquality")
public DexEncodedMethod fixupMethod(DexEncodedMethod method) {
DexMethod methodReference = method.getReference();
DexMethod newMethodReference = fixupMethodReference(methodReference);
- if (newMethodReference != methodReference) {
- return recordMethodChange(method, method.toTypeSubstitutedMethod(newMethodReference));
+ if (!methodReference.isIdenticalTo(newMethodReference)) {
+ return recordMethodChange(
+ method, method.toTypeSubstitutedMethodAsInlining(newMethodReference, dexItemFactory));
}
return method;
}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
index 4d339e8..ef55a1f 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
@@ -678,16 +678,8 @@
+ "` back to original program";
}
for (DexEncodedMethod method : clazz.methods()) {
- if (method.isD8R8Synthesized()) {
- // Methods synthesized by D8/R8 may not be mapped.
- continue;
- }
- DexMethod originalMethod = getOriginalMethodSignature(method.getReference());
- assert originalMethods.contains(originalMethod)
- : "Method could not be mapped back: "
- + method.toSourceString()
- + ", originalMethod: "
- + originalMethod.toSourceString();
+ // Methods synthesized by D8/R8 are not mapped, but all non-synthesized must be originals.
+ assert method.isD8R8Synthesized() || originalMethods.contains(method.getReference());
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index 06117ec..d6b92e0 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -142,7 +142,7 @@
DexEncodedMethod.syntheticBuilder()
.setMethod(newMethodReference)
.setAccessFlags(MethodAccessFlags.createForClassInitializer())
- .setCode(classInitializerMerger.getCode(syntheticMethodReference))
+ .setCode(classInitializerMerger.getCode(newMethodReference))
.setClassFileVersion(classInitializerMerger.getCfVersion())
.setApiLevelForDefinition(apiReferenceLevel)
.setApiLevelForCode(apiReferenceLevel)
@@ -176,7 +176,7 @@
}
classMethodsBuilder.addDirectMethod(
newMethod != method.getReference()
- ? definition.toTypeSubstitutedMethod(newMethod)
+ ? definition.toTypeSubstitutedMethodAsInlining(newMethod, dexItemFactory)
: method.getDefinition());
if (definition.getReference() != newMethod) {
lensBuilder.moveMethod(definition.getReference(), newMethod);
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java
index d4cb598..76c4d8a 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java
@@ -41,9 +41,8 @@
Int2ReferenceSortedMap<DexMethod> typeConstructors,
DexMethod newConstructor,
DexField classIdField,
- Position callerPosition,
- DexMethod originalMethod) {
- super(newConstructor.holder, newConstructor, callerPosition, originalMethod);
+ Position callerPosition) {
+ super(newConstructor.holder, newConstructor, callerPosition);
this.typeConstructors = typeConstructors;
this.classIdField = classIdField;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java
index abb1fbf..7e37921 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java
@@ -11,6 +11,8 @@
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.IRCode;
@@ -35,6 +37,18 @@
ProgramMethod method,
HorizontalClassMergerGraphLens lens);
+ @Override
+ public final Code getCodeAsInlining(
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ // This code object is synthesized so "inlining" just "strips" the callee position.
+ assert isCalleeD8R8Synthesized;
+ return this;
+ }
+
// Implement Code.
@Override
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
index a77873f..837157e 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
@@ -48,7 +48,6 @@
private final DexField classIdField;
private final int extraNulls;
private final DexMethod originalMethodReference;
- private final DexMethod syntheticMethodReference;
private final Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPre;
private final Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPost;
@@ -60,7 +59,6 @@
DexField classIdField,
int extraNulls,
DexMethod originalMethodReference,
- DexMethod syntheticMethodReference,
Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPre,
Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPost,
DexMethod parentConstructor,
@@ -68,7 +66,6 @@
this.classIdField = classIdField;
this.extraNulls = extraNulls;
this.originalMethodReference = originalMethodReference;
- this.syntheticMethodReference = syntheticMethodReference;
this.instanceFieldAssignmentsPre = instanceFieldAssignmentsPre;
this.instanceFieldAssignmentsPost = instanceFieldAssignmentsPost;
this.parentConstructor = parentConstructor;
@@ -90,16 +87,13 @@
IntBox maxStack = new IntBox();
ImmutableList.Builder<CfInstruction> instructionBuilder = ImmutableList.builder();
- // Set position.
- Position callerPosition =
- SyntheticPosition.builder().setLine(0).setMethod(syntheticMethodReference).build();
- Position calleePosition =
+ Position preamblePosition =
SyntheticPosition.builder()
.setLine(0)
- .setMethod(originalMethodReference)
- .setCallerPosition(callerPosition)
+ .setMethod(method.getReference())
+ .setIsD8R8Synthesized(method.getDefinition().isD8R8Synthesized())
.build();
- CfPosition position = new CfPosition(new CfLabel(), calleePosition);
+ CfPosition position = new CfPosition(new CfLabel(), preamblePosition);
instructionBuilder.add(position);
instructionBuilder.add(position.getLabel());
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java
index b2421bb..2360c36 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java
@@ -71,12 +71,9 @@
* Transform this description into actual CF code.
*
* @param originalMethodReference the original reference of the representative method
- * @param syntheticMethodReference the original, synthetic reference of the new method reference
- * ($r8$init$synthetic)
*/
public IncompleteMergedInstanceInitializerCode createCfCode(
DexMethod originalMethodReference,
- DexMethod syntheticMethodReference,
MergeGroup group,
boolean hasClassId,
int extraNulls) {
@@ -84,7 +81,6 @@
hasClassId ? group.getClassIdField() : null,
extraNulls,
originalMethodReference,
- syntheticMethodReference,
instanceFieldAssignmentsPre,
instanceFieldAssignmentsPost,
parentConstructor,
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java
index 91bfef0..22099a3 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java
@@ -253,7 +253,9 @@
classMethodsBuilder::isFresh);
DexEncodedMethod encodedMethod =
- instanceInitializer.getDefinition().toTypeSubstitutedMethod(method);
+ instanceInitializer
+ .getDefinition()
+ .toTypeSubstitutedMethodAsInlining(method, dexItemFactory);
encodedMethod.getMutableOptimizationInfo().markForceInline();
encodedMethod.getAccessFlags().unsetConstructor();
encodedMethod.getAccessFlags().unsetPublic();
@@ -270,26 +272,19 @@
}
private Code getNewCode(
- DexMethod newMethodReference,
- DexMethod syntheticMethodReference,
boolean needsClassId,
int extraNulls) {
if (hasInstanceInitializerDescription()) {
return instanceInitializerDescription.createCfCode(
getOriginalMethodReference(),
- syntheticMethodReference,
group,
needsClassId,
extraNulls);
}
- if (!useSyntheticMethod()) {
- return getRepresentative().getDefinition().getCode();
- }
+ assert useSyntheticMethod();
return new ConstructorEntryPointSynthesizedCode(
createClassIdToInstanceInitializerMap(),
- newMethodReference,
- group.hasClassIdField() ? group.getClassIdField() : null,
- syntheticMethodReference);
+ group.hasClassIdField() ? group.getClassIdField() : null);
}
private boolean isSingleton() {
@@ -381,24 +376,23 @@
}
DexEncodedMethod representativeMethod = representative.getDefinition();
- boolean useSynthethicBuilder = useSyntheticMethod() || representativeMethod.isD8R8Synthesized();
- DexEncodedMethod newInstanceInitializer =
- (useSynthethicBuilder ? DexEncodedMethod.syntheticBuilder() : DexEncodedMethod.builder())
- .setMethod(newMethodReference)
- .setAccessFlags(
- useSynthethicBuilder
- ? getNewAccessFlags()
- : representative.getAccessFlags().withPublic())
- .setCode(
- getNewCode(
- newMethodReference,
- syntheticMethodReference,
- needsClassId,
- extraUnusedNullParameters.size()))
- .setClassFileVersion(getNewClassFileVersion())
- .setApiLevelForDefinition(representativeMethod.getApiLevelForDefinition())
- .setApiLevelForCode(representativeMethod.getApiLevelForCode())
- .build();
+
+ DexEncodedMethod newInstanceInitializer;
+ if (!hasInstanceInitializerDescription() && !useSyntheticMethod()) {
+ newInstanceInitializer =
+ representativeMethod.toTypeSubstitutedMethodAsInlining(
+ newMethodReference, dexItemFactory);
+ } else {
+ newInstanceInitializer =
+ DexEncodedMethod.syntheticBuilder()
+ .setMethod(newMethodReference)
+ .setAccessFlags(getNewAccessFlags())
+ .setCode(getNewCode(needsClassId, extraUnusedNullParameters.size()))
+ .setClassFileVersion(getNewClassFileVersion())
+ .setApiLevelForDefinition(representativeMethod.getApiLevelForDefinition())
+ .setApiLevelForCode(representativeMethod.getApiLevelForCode())
+ .build();
+ }
classMethodsBuilder.addDirectMethod(newInstanceInitializer);
if (mode.isFinal()) {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
index 8cca85f..538c0d3 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
@@ -237,7 +237,7 @@
newMethodSignature.withHolder(originalMethodReference, dexItemFactory);
lensBuilder.fixupMethod(originalMethodReference, newMethodReference);
return newMethodReference != originalMethodReference
- ? method.toTypeSubstitutedMethod(newMethodReference)
+ ? method.toTypeSubstitutedMethodAsInlining(newMethodReference, dexItemFactory)
: method;
}
@@ -278,7 +278,8 @@
lensBuilder.fixupMethod(originalMethodReference, newMethodReference);
- DexEncodedMethod newMethod = method.toTypeSubstitutedMethod(newMethodReference);
+ DexEncodedMethod newMethod =
+ method.toTypeSubstitutedMethodAsInlining(newMethodReference, dexItemFactory);
if (newMethod.isNonPrivateVirtualMethod()) {
// Since we changed the return type or one of the parameters, this method cannot be a
// classpath or library method override, since we only class merge program classes.
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index eca0a6f..5b1ee78 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -124,7 +124,8 @@
group.getTarget().getType(),
classMethodsBuilder::isFresh);
- DexEncodedMethod encodedMethod = oldMethod.getDefinition().toTypeSubstitutedMethod(method);
+ DexEncodedMethod encodedMethod =
+ oldMethod.getDefinition().toTypeSubstitutedMethodAsInlining(method, dexItemFactory);
MethodAccessFlags flags = encodedMethod.getAccessFlags();
flags.unsetProtected();
flags.unsetPublic();
@@ -235,8 +236,9 @@
newMethod =
representative
.getDefinition()
- .toTypeSubstitutedMethod(
+ .toTypeSubstitutedMethodAsInlining(
newMethodReference,
+ dexItemFactory,
builder -> builder.setIsLibraryMethodOverrideIfKnown(isLibraryMethodOverride));
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java
index b4d26cd..a0b8b9b 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java
@@ -82,7 +82,7 @@
classInitializer -> classInitializer.getDefinition().getCode().isCfCode());
return new CfCodeBuilder().build(syntheticMethodReference);
}
- return new IRProvider(classInitializers, syntheticMethodReference);
+ return new IRProvider(classInitializers);
}
public CfVersion getCfVersion() {
@@ -141,7 +141,11 @@
// Building the instructions will adjust maxStack and maxLocals. Build it here before invoking
// the CfCode constructor to ensure that the value passed in is the updated values.
Position callerPosition =
- SyntheticPosition.builder().setLine(0).setMethod(syntheticMethodReference).build();
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(syntheticMethodReference)
+ .setIsD8R8Synthesized(true)
+ .build();
List<CfInstruction> instructions = buildInstructions(callerPosition);
return new CfCode(
syntheticMethodReference.getHolderType(), maxStack, maxLocals, instructions);
@@ -163,13 +167,15 @@
CfLabel endLabel = new CfLabel();
boolean requiresLabel = false;
int index = 1;
+ boolean calleeD8R8Synthesized = method.getDefinition().isD8R8Synthesized();
for (CfInstruction instruction : code.getInstructions()) {
if (instruction.isPosition()) {
- CfPosition cfPosition = instruction.asPosition();
+ CfPosition calleePosition = instruction.asPosition();
newInstructions.add(
new CfPosition(
- cfPosition.getLabel(),
- cfPosition.getPosition().withOutermostCallerPosition(callerPosition)));
+ calleePosition.getLabel(),
+ Code.newInlineePosition(
+ callerPosition, calleePosition.getPosition(), calleeD8R8Synthesized)));
} else if (instruction.isReturn()) {
if (code.getInstructions().size() != index) {
newInstructions.add(new CfGoto(endLabel));
@@ -193,12 +199,9 @@
static class IRProvider extends Code {
private final ImmutableList<ProgramMethod> classInitializers;
- private final DexMethod syntheticMethodReference;
- private IRProvider(
- ImmutableList<ProgramMethod> classInitializers, DexMethod syntheticMethodReference) {
+ private IRProvider(ImmutableList<ProgramMethod> classInitializers) {
this.classInitializers = classInitializers;
- this.syntheticMethodReference = syntheticMethodReference;
}
@Override
@@ -209,8 +212,13 @@
MutableMethodConversionOptions conversionOptions) {
assert !classInitializers.isEmpty();
- Position callerPosition =
- SyntheticPosition.builder().setLine(0).setMethod(syntheticMethodReference).build();
+ Position preamblePosition =
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(method.getReference())
+ .setIsD8R8Synthesized(method.getDefinition().isD8R8Synthesized())
+ .build();
+
IRMetadata metadata = new IRMetadata();
NumberGenerator blockNumberGenerator = new NumberGenerator();
NumberGenerator valueNumberGenerator = new NumberGenerator();
@@ -223,7 +231,7 @@
block.add(
InvokeStatic.builder()
.setMethod(classInitializer.getReference())
- .setPosition(callerPosition)
+ .setPosition(preamblePosition)
.build(),
metadata);
}
@@ -236,7 +244,7 @@
new IRCode(
appView.options(),
method,
- callerPosition,
+ preamblePosition,
ListUtils.newLinkedList(block),
valueNumberGenerator,
blockNumberGenerator,
@@ -266,7 +274,7 @@
appView,
appView.codeLens(),
valueNumberGenerator,
- callerPosition,
+ preamblePosition,
classInitializer.getOrigin(),
RewrittenPrototypeDescription.none());
classInitializer.getDefinition().setObsolete();
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java
index 60903cc..d9e08c8 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java
@@ -14,27 +14,20 @@
import java.util.function.Consumer;
public class ConstructorEntryPointSynthesizedCode extends AbstractSynthesizedCode {
- private final DexMethod newConstructor;
- private final DexMethod originalMethod;
private final DexField classIdField;
private final Int2ReferenceSortedMap<DexMethod> typeConstructors;
public ConstructorEntryPointSynthesizedCode(
- Int2ReferenceSortedMap<DexMethod> typeConstructors,
- DexMethod newConstructor,
- DexField classIdField,
- DexMethod originalMethod) {
+ Int2ReferenceSortedMap<DexMethod> typeConstructors, DexField classIdField) {
this.typeConstructors = typeConstructors;
- this.newConstructor = newConstructor;
this.classIdField = classIdField;
- this.originalMethod = originalMethod;
}
@Override
public SourceCodeProvider getSourceCodeProvider() {
- return (ignored, callerPosition) ->
+ return (method, callerPosition) ->
new ConstructorEntryPoint(
- typeConstructors, newConstructor, classIdField, callerPosition, originalMethod);
+ typeConstructors, method.getReference(), classIdField, callerPosition);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java b/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java
index 1a07f41..89e7c36 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java
@@ -34,7 +34,12 @@
canonicalPositions =
new HashMap<>(1 + (callerPosition == null ? 0 : 1) + expectedPositionsCount);
if (preamblePosition == null) {
- preamblePosition = SyntheticPosition.builder().setLine(0).setMethod(method).build();
+ preamblePosition =
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(method)
+ .setIsD8R8Synthesized(methodIsSynthesized)
+ .build();
}
if (callerPosition != null) {
this.callerPosition = getCanonical(callerPosition);
@@ -62,6 +67,18 @@
return canonical != null ? canonical : position;
}
+ public Position canonicalizePositionWithCaller(Position position) {
+ if (position.isD8R8Synthesized() && callerPosition != null) {
+ assert !position.hasCallerPosition();
+ return getCanonical(Code.newInlineePosition(callerPosition, position, true));
+ }
+ return getCanonical(
+ position
+ .builderWithCopy()
+ .setCallerPosition(canonicalizeCallerPosition(position.getCallerPosition()))
+ .build());
+ }
+
/**
* Append callerPosition (supplied in constructor) to the end of caller's caller chain and return
* the canonical instance.
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 187fe6a..48432c4 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
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.code;
-import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.ProgramMethod;
@@ -41,6 +40,8 @@
Position callerPosition,
boolean removeInnerFramesIfThrowingNpe,
boolean isD8R8Synthesized) {
+ assert callerPosition == null || !isD8R8Synthesized
+ : "Synthetic positions should always be outermost";
this.line = line;
this.method = method;
this.callerPosition = callerPosition;
@@ -128,30 +129,20 @@
.withBool(Position::isD8R8Synthesized);
}
- @SuppressWarnings("ReferenceEquality")
public static Position syntheticNone() {
return SyntheticPosition.NO_POSITION_SYNTHETIC;
}
- @SuppressWarnings("ReferenceEquality")
- public static Position getPositionForInlining(
- AppView<?> appView, InvokeMethod invoke, ProgramMethod context) {
+ public static Position getPositionForInlining(InvokeMethod invoke, ProgramMethod context) {
Position position = invoke.getPosition();
if (position.method == null) {
assert position.isNone();
position = SourcePosition.builder().setMethod(context.getReference()).build();
}
- if (context.getDefinition().isD8R8Synthesized()) {
- // Some rewritings map a synthetic method back to an original in the program. To ensure we
- // have correct line information we have to rewrite the positions as inline position
- // therefore we only check if the original method is present.
- DexMethod originalMethodSignature =
- appView.graphLens().getOriginalMethodSignature(context.getReference());
- assert position.hasMethodInChain(originalMethodSignature);
- } else {
- assert position.getOutermostCaller().method
- == appView.graphLens().getOriginalMethodSignature(context.getReference());
- }
+ // If this assert is hit, then the method has changed/moved and the position info has not been
+ // updated. The code changing/moving the method needs to use the "AsInlining" helpers to
+ // maintain correct mapping information.
+ assert context.getReference().isIdenticalTo(position.getOutermostCaller().getMethod());
return position;
}
@@ -198,22 +189,6 @@
return null;
}
- public boolean hasPositionMatching(Predicate<Position> positionPredicate) {
- Position lastPosition = this;
- while (lastPosition != null) {
- if (positionPredicate.test(lastPosition)) {
- return true;
- }
- lastPosition = lastPosition.getCallerPosition();
- }
- return false;
- }
-
- @SuppressWarnings("ReferenceEquality")
- public boolean hasMethodInChain(DexMethod method) {
- return hasPositionMatching(position -> position.getMethod() == method);
- }
-
public Position withOutermostCallerPosition(Position newOutermostCallerPosition) {
return builderWithCopy()
.setCallerPosition(
@@ -497,13 +472,23 @@
public static class OutlinePosition extends Position {
+ // This is the method that the outline is created at. This needs to stay stable as it is used
+ // to identify the mapping table between callers and this outline definition.
+ private final DexMethod outlineMethodKey;
+
private OutlinePosition(
int line,
DexMethod method,
Position callerPosition,
boolean removeInnerFramesIfThrowingNpe,
- boolean isD8R8Synthesized) {
- super(line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
+ DexMethod outlineMethodKey) {
+ super(line, method, callerPosition, removeInnerFramesIfThrowingNpe, true);
+ this.outlineMethodKey = outlineMethodKey;
+ assert outlineMethodKey != null;
+ }
+
+ public DexMethod getOutlineMethodKey() {
+ return outlineMethodKey;
}
@Override
@@ -518,7 +503,7 @@
@Override
public PositionBuilder<?, ?> builderWithCopy() {
- return builder()
+ return builder(outlineMethodKey)
.setLine(line)
.setMethod(method)
.setCallerPosition(callerPosition)
@@ -531,13 +516,15 @@
return Position::specifyBasePosition;
}
- public static OutlinePositionBuilder builder() {
- return new OutlinePositionBuilder();
+ public static OutlinePositionBuilder builder(DexMethod outlineMethodKey) {
+ return new OutlinePositionBuilder().setOutlineMethodKey(outlineMethodKey);
}
public static class OutlinePositionBuilder
extends PositionBuilder<OutlinePosition, OutlinePositionBuilder> {
+ private DexMethod outlineMethodKey;
+
private OutlinePositionBuilder() {}
@Override
@@ -545,10 +532,17 @@
return this;
}
+ // Intentionally hidden without external setter.
+ private OutlinePositionBuilder setOutlineMethodKey(DexMethod outlineMethodKey) {
+ this.outlineMethodKey = outlineMethodKey;
+ return this;
+ }
+
@Override
public OutlinePosition build() {
+ assert isD8R8Synthesized;
return new OutlinePosition(
- line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
+ line, method, callerPosition, removeInnerFramesIfThrowingNpe, outlineMethodKey);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index 424108f..de8a584 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -27,7 +27,6 @@
import com.android.tools.r8.graph.DebugLocalInfo.PrintLevel;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.CanonicalPositions;
@@ -210,7 +209,6 @@
CfCode code,
List<CfCode.LocalVariableInfo> localVariables,
ProgramMethod method,
- DexMethod originalMethod,
Position callerPosition,
Origin origin,
AppView<?> appView) {
@@ -234,7 +232,7 @@
new CanonicalPositions(
callerPosition,
cfPositionCount,
- originalMethod,
+ method.getReference(),
method.getDefinition().isD8R8Synthesized(),
code.getPreamblePosition());
internalOutputMode = appView.options().getInternalOutputMode();
@@ -904,11 +902,6 @@
}
public Position getCanonicalPosition(Position position) {
- return canonicalPositions.getCanonical(
- position
- .builderWithCopy()
- .setCallerPosition(
- canonicalPositions.canonicalizeCallerPosition(position.getCallerPosition()))
- .build());
+ return canonicalPositions.canonicalizePositionWithCaller(position);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
index 2edb76d..b830c14 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
@@ -74,29 +74,28 @@
private final CanonicalPositions canonicalPositions;
private List<DexDebugEntry> debugEntries = null;
- // In case of inlining the position of the invoke in the caller.
- private final DexMethod originalMethod;
public DexSourceCode(
DexCode code,
ProgramMethod method,
- DexMethod originalMethod,
Position callerPosition,
DexItemFactory factory) {
this.code = code;
this.method = method;
- this.originalMethod = originalMethod;
+ DexMethod reference = method.getReference();
+ boolean d8R8Synthesized = method.getDefinition().isD8R8Synthesized();
EventBasedDebugInfo info = DexDebugInfo.convertToEventBased(code, factory);
if (info != null) {
- debugEntries = info.computeEntries(originalMethod);
+ debugEntries = info.computeEntries(reference, d8R8Synthesized);
}
canonicalPositions =
new CanonicalPositions(
callerPosition,
debugEntries == null ? 0 : debugEntries.size(),
- originalMethod,
- method.getDefinition().isD8R8Synthesized(),
- DexDebugUtils.computePreamblePosition(originalMethod, info).getFramePosition());
+ reference,
+ d8R8Synthesized,
+ DexDebugUtils.computePreamblePosition(reference, d8R8Synthesized, info)
+ .getFramePosition());
}
@Override
@@ -261,17 +260,7 @@
}
private Position getCanonicalPositionAppendCaller(DexDebugEntry entry) {
- // If this instruction has already been inlined then the original method must be in the caller
- // chain.
- Position position = entry.getPosition();
- // TODO(b/261971803): The original method should probably always be in the chain.
- assert !position.hasCallerPosition() || position.hasMethodInChain(originalMethod);
- return canonicalPositions.getCanonical(
- position
- .builderWithCopy()
- .setCallerPosition(
- canonicalPositions.canonicalizeCallerPosition(position.getCallerPosition()))
- .build());
+ return canonicalPositions.canonicalizePositionWithCaller(entry.getPosition());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 0341252..735df70 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1053,7 +1053,6 @@
appView,
null,
RewrittenPrototypeDescription.none(),
- appView.graphLens().getOriginalMethodSignature(code.context().getReference()),
(MutableMethodConversionOptions) code.getConversionOptions());
timing.end();
return irCode;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 44f9afd..46988a7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
@@ -675,6 +676,8 @@
newAccessFlags.unsetPrivate();
// Always make the method public to provide access.
newAccessFlags.setPublic();
+ Code code = encodedMethod.getCode();
+ DexItemFactory factory = appView.dexItemFactory();
DexEncodedMethod newMethod =
DexEncodedMethod.syntheticBuilder()
.setMethod(callTarget)
@@ -683,10 +686,12 @@
.setAnnotations(encodedMethod.annotations())
.setParameterAnnotations(encodedMethod.parameterAnnotationsList)
.setCode(
- encodedMethod
- .getCode()
- .getCodeAsInlining(
- callTarget, encodedMethod, appView.dexItemFactory()))
+ code.getCodeAsInlining(
+ callTarget,
+ true,
+ encodedMethod.getReference(),
+ encodedMethod.isD8R8Synthesized(),
+ factory))
.setApiLevelForDefinition(encodedMethod.getApiLevelForDefinition())
.setApiLevelForCode(encodedMethod.getApiLevelForCode())
.build();
@@ -770,6 +775,8 @@
// its accessibility and make it virtual.
MethodAccessFlags newAccessFlags = encodedMethod.accessFlags.copy();
newAccessFlags.unsetPrivate();
+ Code code = encodedMethod.getCode();
+ DexItemFactory factory = appView.dexItemFactory();
DexEncodedMethod newMethod =
DexEncodedMethod.syntheticBuilder()
.setMethod(callTarget)
@@ -778,10 +785,12 @@
.setAnnotations(encodedMethod.annotations())
.setParameterAnnotations(encodedMethod.parameterAnnotationsList)
.setCode(
- encodedMethod
- .getCode()
- .getCodeAsInlining(
- callTarget, encodedMethod, appView.dexItemFactory()))
+ code.getCodeAsInlining(
+ callTarget,
+ true,
+ encodedMethod.getReference(),
+ encodedMethod.isD8R8Synthesized(),
+ factory))
.setApiLevelForDefinition(encodedMethod.getApiLevelForDefinition())
.setApiLevelForCode(encodedMethod.getApiLevelForCode())
.build();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
index 092423e..0dd9fec 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
@@ -108,7 +108,7 @@
if (clazz.lookupProgramMethod(bridgeReference) == null) {
// Create a new private method holding the code of the virtual method.
ProgramMethod newDirectMethod =
- method.getDefinition().toPrivateSyntheticMethod(clazz, bridgeReference);
+ method.getDefinition().toPrivateSyntheticMethod(clazz, bridgeReference, dexItemFactory);
// Create the new cf code object for the virtual method.
CfCode virtualMethodCode =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index 21771de..4fff3f5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -457,10 +457,12 @@
// Represent a static interface method as a method of companion class.
private DexMethod staticAsMethodOfCompanionClass(DexClassAndMethod method) {
- DexItemFactory dexItemFactory = appView.dexItemFactory();
- DexType companionClassType = getCompanionClassType(method.getHolderType(), dexItemFactory);
- DexMethod rewritten = method.getReference().withHolder(companionClassType, dexItemFactory);
- return rewritten;
+ return staticAsMethodOfCompanionClass(method.getReference(), appView.dexItemFactory());
+ }
+
+ public static DexMethod staticAsMethodOfCompanionClass(DexMethod method, DexItemFactory factory) {
+ DexType companionClassType = getCompanionClassType(method.getHolderType(), factory);
+ return method.withHolder(companionClassType, factory);
}
private static DexMethod instanceAsMethodOfCompanionClass(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index 7ac6713..1e53aa6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -204,7 +204,11 @@
definition
.getCode()
.getCodeAsInlining(
- companion.getReference(), method.getDefinition(), appView.dexItemFactory());
+ companion.getReference(),
+ companion.getDefinition().isD8R8Synthesized(),
+ method.getReference(),
+ method.getDefinition().isD8R8Synthesized(),
+ appView.dexItemFactory());
if (!definition.isStatic()) {
DexEncodedMethod.setDebugInfoWithFakeThisParameter(
code, companion.getReference().getArity(), appView);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index ac0bc7b..627d5ba 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -916,8 +916,9 @@
method, localUtilityClass, availableMethodSignatures, method.getReference());
return method
.getDefinition()
- .toTypeSubstitutedMethod(
+ .toTypeSubstitutedMethodAsInlining(
newMethod,
+ factory,
builder ->
transformMethodForLocalUtility(builder, method)
.setCompilationState(method.getDefinition().getCompilationState()));
@@ -934,8 +935,9 @@
DexEncodedMethod dexEncodedMethod =
method
.getDefinition()
- .toTypeSubstitutedMethod(
+ .toTypeSubstitutedMethodAsInlining(
newMethod,
+ factory,
builder ->
transformMethodForLocalUtility(builder, method)
.modifyAccessFlags(MethodAccessFlags::unsetAbstract)
@@ -1016,8 +1018,9 @@
RewrittenPrototypeDescription prototypeChanges =
lensBuilder.moveAndMap(
method.getReference(), newMethod, isStatic, isStatic, extraUnusedNullParameters);
- return method.toTypeSubstitutedMethod(
+ return method.toTypeSubstitutedMethodAsInlining(
newMethod,
+ factory,
builder ->
builder
.fixupOptimizationInfo(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/code/CheckNotZeroCode.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/code/CheckNotZeroCode.java
index 4e7801c..b17f4b6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/code/CheckNotZeroCode.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/code/CheckNotZeroCode.java
@@ -16,6 +16,9 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.NumberGenerator;
+import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.ir.optimize.enums.EnumUnboxerImpl;
@@ -48,7 +51,28 @@
Origin origin,
MutableMethodConversionOptions conversionOptions) {
// Build IR from the checkNotNull() method.
- IRCode code = checkNotNullMethod.buildIR(appView);
+ Position callerPosition =
+ SyntheticPosition.builder()
+ .setMethod(checkNotZeroMethod.getReference())
+ .setLine(0)
+ .setIsD8R8Synthesized(checkNotZeroMethod.getDefinition().isD8R8Synthesized())
+ .build();
+ NumberGenerator valueNumberGenerator = new NumberGenerator();
+ IRCode code =
+ checkNotNullMethod
+ .getDefinition()
+ .getCode()
+ .buildInliningIR(
+ checkNotZeroMethod,
+ checkNotNullMethod,
+ appView,
+ appView.graphLens(),
+ valueNumberGenerator,
+ callerPosition,
+ checkNotZeroMethod.getOrigin(),
+ appView
+ .graphLens()
+ .lookupPrototypeChangesForMethodDefinition(checkNotNullMethod.getReference()));
InstructionListIterator instructionIterator = code.instructionListIterator();
// Start iterating at the argument instruction for the checked argument.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java
index 958b02d..b1e76f3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/InliningIRProvider.java
@@ -84,7 +84,7 @@
context,
appView,
valueNumberGenerator,
- Position.getPositionForInlining(appView, invoke, context),
+ Position.getPositionForInlining(invoke, context),
origin,
methodProcessor);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
index ee3fc44..1fe050f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/OutlinerImpl.java
@@ -341,14 +341,12 @@
}
@Override
- @SuppressWarnings("ReferenceEquality")
public boolean equals(Object other) {
if (!(other instanceof NewInstanceOutlineInstruction)) {
return false;
}
NewInstanceOutlineInstruction o = (NewInstanceOutlineInstruction) other;
- boolean result = clazz == o.clazz;
- return result;
+ return clazz.isIdenticalTo(o.clazz);
}
@Override
@@ -397,9 +395,8 @@
}
@Override
- @SuppressWarnings("ReferenceEquality")
public boolean needsLensRewriting(GraphLens currentGraphLens) {
- return currentGraphLens.lookupType(clazz) != clazz;
+ return !clazz.isIdenticalTo(currentGraphLens.lookupType(clazz));
}
}
@@ -449,13 +446,12 @@
}
@Override
- @SuppressWarnings("ReferenceEquality")
public boolean equals(Object other) {
if (!(other instanceof InvokeOutlineInstruction)) {
return false;
}
InvokeOutlineInstruction o = (InvokeOutlineInstruction) other;
- return method == o.method
+ return method.isIdenticalTo(o.method)
&& invokeType == o.invokeType
&& hasOutValue == o.hasOutValue
&& Objects.equals(proto, o.proto);
@@ -542,9 +538,8 @@
}
@Override
- @SuppressWarnings("ReferenceEquality")
public boolean needsLensRewriting(GraphLens currentGraphLens) {
- return currentGraphLens.getRenamedMethodSignature(method) != method;
+ return !method.isIdenticalTo(currentGraphLens.getRenamedMethodSignature(method));
}
}
@@ -1255,8 +1250,9 @@
argumentsMapIndex = 0;
OutlineCallerPositionBuilder positionBuilder =
OutlineCallerPosition.builder()
- .setMethod(appView.graphLens().getOriginalMethodSignature(method.getReference()))
+ .setMethod(method.getReference())
.setOutlineCallee(outlineMethod)
+ .setIsD8R8Synthesized(method.getDefinition().isD8R8Synthesized())
// We set the line number to 0 here and rely on the LineNumberOptimizer to
// set a new disjoint line.
.setLine(0);
@@ -1739,11 +1735,10 @@
}
@Override
- @SuppressWarnings("ReferenceEquality")
public void buildInstruction(
IRBuilder builder, int instructionIndex, boolean firstBlockInstruction) {
if (instructionIndex == outline.templateInstructions.size()) {
- if (outline.returnType == dexItemFactory.voidType) {
+ if (outline.returnType.isVoidType()) {
builder.addReturn();
} else {
builder.addReturn(outline.argumentCount());
@@ -1790,7 +1785,11 @@
public Position getCurrentPosition() {
// Always build positions for outlinee - each callsite will only build a position map for
// instructions that are actually throwing.
- return OutlinePosition.builder().setLine(position).setMethod(method).build();
+ return OutlinePosition.builder(method)
+ .setLine(position)
+ .setMethod(method)
+ .setIsD8R8Synthesized(true)
+ .build();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java
index f726dda..a51f68a 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/AbstractSynthesizedCode.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.graph.lens.GraphLens;
@@ -51,7 +53,7 @@
}
@Override
- public IRCode buildInliningIR(
+ public final IRCode buildInliningIR(
ProgramMethod context,
ProgramMethod method,
AppView<?> appView,
@@ -72,6 +74,18 @@
}
@Override
+ public final Code getCodeAsInlining(
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ // This code object is synthesized so "inlining" just "strips" the callee position.
+ assert isCalleeD8R8Synthesized;
+ return this;
+ }
+
+ @Override
public final String toString() {
return toString(null, RetracerForCodePrinting.empty());
}
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java
index 24e8151..e62e6ca 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java
@@ -28,7 +28,6 @@
private DexType receiver;
private DexMethod method;
- private DexMethod originalMethod;
private DexType targetReceiver;
private DexMethod target;
private InvokeType invokeType;
@@ -38,7 +37,6 @@
public Builder(DexMethod method) {
this.method = method;
- this.originalMethod = method;
}
public Builder setReceiver(DexType receiver) {
@@ -51,11 +49,6 @@
return this;
}
- public Builder setOriginalMethod(DexMethod originalMethod) {
- this.originalMethod = originalMethod;
- return this;
- }
-
public Builder setTargetReceiver(DexType targetReceiver) {
this.targetReceiver = targetReceiver;
return this;
@@ -90,7 +83,6 @@
return new ForwardMethodSourceCode(
receiver,
method,
- originalMethod,
targetReceiver,
target,
invokeType,
@@ -111,7 +103,6 @@
ForwardMethodSourceCode(
DexType receiver,
DexMethod method,
- DexMethod originalMethod,
DexType targetReceiver,
DexMethod target,
InvokeType invokeType,
@@ -119,7 +110,7 @@
boolean isInterface,
boolean castResult,
boolean extraNullParameter) {
- super(receiver, method, callerPosition, originalMethod);
+ super(receiver, method, callerPosition);
assert (targetReceiver == null) == (invokeType == InvokeType.STATIC);
this.target = target;
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
index f9c13e9..46a3a3a 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
@@ -45,11 +45,6 @@
private final Position position;
protected SyntheticSourceCode(DexType receiver, DexMethod method, Position callerPosition) {
- this(receiver, method, callerPosition, method);
- }
-
- protected SyntheticSourceCode(
- DexType receiver, DexMethod method, Position callerPosition, DexMethod originalMethod) {
assert method != null;
this.receiver = receiver;
this.method = method;
@@ -64,14 +59,16 @@
for (int i = 0; i < paramCount; i++) {
this.paramRegisters[i] = nextRegister(ValueType.fromDexType(params[i]));
}
-
- position =
- SyntheticPosition.builder()
- .setLine(0)
- .setMethod(originalMethod)
- .setCallerPosition(callerPosition)
- .setIsD8R8Synthesized(true)
- .build();
+ // If there is a caller position that is the position of this synthetic code, otherwise
+ // build up a synthetic position.
+ this.position =
+ callerPosition != null
+ ? callerPosition
+ : SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(method)
+ .setIsD8R8Synthesized(true)
+ .build();
}
protected final void add(Consumer<IRBuilder> constructor) {
diff --git a/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java b/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java
index 2e191a7..4c78283 100644
--- a/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java
@@ -39,7 +39,11 @@
this.strategy = strategy;
this.bytecodeMetadataProvider = bytecodeMetadataProvider;
this.builder =
- new LirBuilder<>(irCode.context().getReference(), strategy, options)
+ new LirBuilder<>(
+ irCode.context().getReference(),
+ irCode.context().getDefinition().isD8R8Synthesized(),
+ strategy,
+ options)
.setMetadata(irCode.metadata())
.prepareForBytecodeInstructionMetadata(bytecodeMetadataProvider.size());
}
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index 877794a..1bd59ff 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -31,7 +31,6 @@
import com.android.tools.r8.ir.code.ArrayLength;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
-import com.android.tools.r8.ir.code.CanonicalPositions;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.Cmp;
@@ -82,7 +81,6 @@
import com.android.tools.r8.ir.code.Or;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.code.RecordFieldValues;
import com.android.tools.r8.ir.code.Rem;
import com.android.tools.r8.ir.code.Return;
@@ -104,7 +102,6 @@
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
import com.android.tools.r8.lightir.LirBuilder.StringSwitchPayload;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
-import com.android.tools.r8.lightir.LirCode.StructuredPositionEntry;
import com.android.tools.r8.lightir.LirCode.TryCatchTable;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ListUtils;
@@ -131,12 +128,11 @@
AppView<?> appView,
Position callerPosition,
RewrittenPrototypeDescription protoChanges,
- DexMethod originalMethod,
MutableMethodConversionOptions conversionOptions) {
Parser<EV> parser =
new Parser<>(
lirCode,
- originalMethod,
+ method.getReference(),
method.getDefinition().isD8R8Synthesized(),
appView,
strategy,
@@ -168,7 +164,7 @@
private final AppView<?> appView;
private final LirCode<EV> code;
- private final DexMethod originalMethod;
+ private final DexMethod method;
private final LirDecodingStrategy<Value, EV> strategy;
private final NumberGenerator basicBlockNumberGenerator = new NumberGenerator();
private final RewrittenPrototypeDescription protoChanges;
@@ -188,7 +184,7 @@
public Parser(
LirCode<EV> code,
- DexMethod originalMethod,
+ DexMethod method,
boolean isD8R8Synthesized,
AppView<?> appView,
LirDecodingStrategy<Value, EV> strategy,
@@ -197,7 +193,7 @@
super(code);
this.appView = appView;
this.code = code;
- this.originalMethod = originalMethod;
+ this.method = method;
this.strategy = strategy;
this.protoChanges = protoChanges;
assert protoChanges != null;
@@ -205,43 +201,14 @@
buildForInlining = false;
positionTable = code.getPositionTable();
// Recreate the preamble position. This is active for arguments and code with no positions.
- currentPosition = SyntheticPosition.builder().setLine(0).setMethod(originalMethod).build();
+ currentPosition = code.getPreamblePosition(method, isD8R8Synthesized);
} else {
buildForInlining = true;
- PositionEntry[] inlineePositions = code.getPositionTable();
- Position inlineePreamble = null;
- if (inlineePositions.length > 0 && inlineePositions[0].getFromInstructionIndex() == 0) {
- inlineePreamble = inlineePositions[0].getPosition(originalMethod);
- }
- CanonicalPositions canonicalPositions =
- new CanonicalPositions(
- callerPosition,
- inlineePositions.length,
- originalMethod,
- isD8R8Synthesized,
- inlineePreamble);
- currentPosition = canonicalPositions.getPreamblePosition();
- positionTable = new PositionEntry[inlineePositions.length];
- for (int i = 0; i < inlineePositions.length; i++) {
- PositionEntry inlineeEntry = inlineePositions[i];
- Position inlineePosition = inlineeEntry.getPosition(originalMethod);
- positionTable[i] =
- new StructuredPositionEntry(
- inlineeEntry.getFromInstructionIndex(),
- canonicalPositions.getCanonical(
- inlineePosition
- .builderWithCopy()
- .setCallerPosition(
- canonicalPositions.canonicalizeCallerPosition(
- inlineePosition.getCallerPosition()))
- .build()));
- }
+ positionTable =
+ code.getPositionTableAsInlining(
+ callerPosition, method, isD8R8Synthesized, preamble -> currentPosition = preamble);
}
- if (positionTable.length > 0 && positionTable[0].getFromInstructionIndex() == 0) {
- entryPosition = positionTable[0].getPosition(originalMethod);
- } else {
- entryPosition = currentPosition;
- }
+ entryPosition = currentPosition;
}
@Override
@@ -275,7 +242,9 @@
private void ensureCurrentPosition() {
if (nextPositionEntry != null
&& nextPositionEntry.getFromInstructionIndex() <= nextInstructionIndex) {
- currentPosition = nextPositionEntry.getPosition(originalMethod);
+ currentPosition =
+ nextPositionEntry.getPosition(
+ method, entryPosition.getOutermostCaller().isD8R8Synthesized());
advanceNextPositionEntry();
}
}
@@ -501,7 +470,6 @@
private Argument internalAddArgument(Value dest, boolean isBooleanType) {
assert currentBlock != null;
- assert currentPosition.isSyntheticPosition() || buildForInlining;
// Arguments are not included in the "instructions" so this does not call "addInstruction"
// which would otherwise advance the state.
Argument argument = new Argument(dest, currentBlock.size(), isBooleanType);
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
index d222f5f..5d988d8 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -276,13 +276,21 @@
}
public LirBuilder(
- DexMethod method, LirEncodingStrategy<V, EV> strategy, InternalOptions options) {
+ DexMethod method,
+ boolean isD8R8Synthesized,
+ LirEncodingStrategy<V, EV> strategy,
+ InternalOptions options) {
useDexEstimationStrategy = options.isGeneratingDex();
factory = options.dexItemFactory();
constants = new Reference2IntOpenHashMap<>();
positionTable = new ArrayList<>();
this.strategy = strategy;
- currentPosition = SyntheticPosition.builder().setLine(0).setMethod(method).build();
+ currentPosition =
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(method)
+ .setIsD8R8Synthesized(isD8R8Synthesized)
+ .build();
flushedPosition = currentPosition;
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java
index f79a18f..8270d8a 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -21,12 +21,14 @@
import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadata;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.ir.code.CanonicalPositions;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.IRMetadata;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SourcePosition;
+import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.ir.conversion.MethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
@@ -59,6 +61,8 @@
public abstract static class PositionEntry implements StructuralItem<PositionEntry> {
+ public static final PositionEntry[] EMPTY_ARRAY = new PositionEntry[0];
+
private final int fromInstructionIndex;
PositionEntry(int fromInstructionIndex) {
@@ -69,7 +73,7 @@
return fromInstructionIndex;
}
- public abstract Position getPosition(DexMethod method);
+ public abstract Position getPosition(DexMethod method, boolean isD8R8Synthesized);
abstract int getOrder();
@@ -116,8 +120,12 @@
}
@Override
- public Position getPosition(DexMethod method) {
- return SourcePosition.builder().setMethod(method).setLine(line).build();
+ public Position getPosition(DexMethod method, boolean isD8R8Synthesized) {
+ return (isD8R8Synthesized ? SyntheticPosition.builder() : SourcePosition.builder())
+ .setMethod(method)
+ .setIsD8R8Synthesized(isD8R8Synthesized)
+ .setLine(line)
+ .build();
}
@Override
@@ -145,7 +153,7 @@
}
@Override
- public Position getPosition(DexMethod method) {
+ public Position getPosition(DexMethod method, boolean isD8R8Synthesized) {
return position;
}
@@ -344,8 +352,11 @@
private Int2ReferenceMap<BytecodeInstructionMetadata> metadataMap;
public static <V, EV> LirBuilder<V, EV> builder(
- DexMethod method, LirEncodingStrategy<V, EV> strategy, InternalOptions options) {
- return new LirBuilder<>(method, strategy, options);
+ DexMethod method,
+ boolean isD8R8Synthesized,
+ LirEncodingStrategy<V, EV> strategy,
+ InternalOptions options) {
+ return new LirBuilder<>(method, isD8R8Synthesized, strategy, options);
}
private static <EV> void specify(StructuralSpecification<LirCode<EV>, ?> spec) {
@@ -366,7 +377,7 @@
LirCode(
IRMetadata irMetadata,
LirConstant[] constants,
- PositionEntry[] positions,
+ PositionEntry[] positionTable,
int argumentCount,
byte[] instructions,
int instructionCount,
@@ -375,9 +386,10 @@
LirStrategyInfo<EV> strategyInfo,
boolean useDexEstimationStrategy,
Int2ReferenceMap<BytecodeInstructionMetadata> metadataMap) {
+ assert positionTable != null;
this.irMetadata = irMetadata;
this.constants = constants;
- this.positionTable = positions;
+ this.positionTable = positionTable;
this.argumentCount = argumentCount;
this.instructions = instructions;
this.instructionCount = instructionCount;
@@ -540,7 +552,6 @@
appView,
callerPosition,
protoChanges,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
conversionOptions);
}
@@ -634,9 +645,78 @@
}
}
+ public Position getPreamblePosition(DexMethod method, boolean isD8R8Synthesized) {
+ if (positionTable.length > 0 && positionTable[0].fromInstructionIndex == 0) {
+ return positionTable[0].getPosition(method, isD8R8Synthesized);
+ }
+ return SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(method)
+ .setIsD8R8Synthesized(isD8R8Synthesized)
+ .build();
+ }
+
+ public PositionEntry[] getPositionTableAsInlining(
+ Position callerPosition,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ Consumer<Position> preamblePositionConsumer) {
+ // Fast path for moving a synthetic method with no actual line info.
+ if (isCalleeD8R8Synthesized && positionTable.length == 0) {
+ preamblePositionConsumer.accept(callerPosition);
+ return PositionEntry.EMPTY_ARRAY;
+ }
+ Position calleePreamble = getPreamblePosition(callee, isCalleeD8R8Synthesized);
+ CanonicalPositions canonicalPositions =
+ new CanonicalPositions(
+ callerPosition, positionTable.length, callee, isCalleeD8R8Synthesized, calleePreamble);
+ PositionEntry[] newPositionTable;
+ if (positionTable.length == 0) {
+ newPositionTable =
+ new PositionEntry[] {
+ new StructuredPositionEntry(0, canonicalPositions.getPreamblePosition())
+ };
+ } else {
+ newPositionTable = new PositionEntry[positionTable.length];
+ for (int i = 0; i < positionTable.length; i++) {
+ PositionEntry inlineeEntry = positionTable[i];
+ Position inlineePosition = inlineeEntry.getPosition(callee, isCalleeD8R8Synthesized);
+ newPositionTable[i] =
+ new StructuredPositionEntry(
+ inlineeEntry.getFromInstructionIndex(),
+ canonicalPositions.canonicalizePositionWithCaller(inlineePosition));
+ }
+ }
+ preamblePositionConsumer.accept(canonicalPositions.getPreamblePosition());
+ return newPositionTable;
+ }
+
@Override
- public Code getCodeAsInlining(DexMethod caller, DexEncodedMethod callee, DexItemFactory factory) {
- throw new Unimplemented();
+ public Code getCodeAsInlining(
+ DexMethod caller,
+ boolean isCallerD8R8Synthesized,
+ DexMethod callee,
+ boolean isCalleeD8R8Synthesized,
+ DexItemFactory factory) {
+ Position callerPosition =
+ SyntheticPosition.builder().setLine(0).setMethod(caller).setIsD8R8Synthesized(true).build();
+ PositionEntry[] newPositionTable =
+ getPositionTableAsInlining(callerPosition, callee, isCalleeD8R8Synthesized, unused -> {});
+ if (Arrays.equals(positionTable, newPositionTable)) {
+ return this;
+ }
+ return new LirCode<>(
+ irMetadata,
+ constants,
+ newPositionTable,
+ argumentCount,
+ instructions,
+ instructionCount,
+ tryCatchTable,
+ debugLocalInfoTable,
+ strategyInfo,
+ useDexEstimationStrategy,
+ metadataMap);
}
@Override
@@ -662,9 +742,10 @@
}
@Override
- public void forEachPosition(DexMethod method, Consumer<Position> positionConsumer) {
+ public void forEachPosition(
+ DexMethod method, boolean isD8R8Synthesized, Consumer<Position> positionConsumer) {
for (PositionEntry entry : positionTable) {
- positionConsumer.accept(entry.getPosition(method));
+ positionConsumer.accept(entry.getPosition(method, isD8R8Synthesized));
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index 24fb83a..588666a 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -8,6 +8,7 @@
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.defaultAsMethodOfCompanionClass;
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceClassType;
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.isCompanionClassType;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.staticAsMethodOfCompanionClass;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -77,7 +78,7 @@
// To keep the order deterministic, we sort the classes by their type, which is a unique key.
private final Set<ProgramOrClasspathClass> mappedClasses = Sets.newIdentityHashSet();
private final Map<DexReference, MemberNaming> memberNames = Maps.newIdentityHashMap();
- private final Map<DexMethod, DexString> defaultInterfaceMethodImplementationNames =
+ private final Map<DexMethod, DexString> companionClassInterfaceMethodImplementationNames =
Maps.newIdentityHashMap();
private final Map<DexMethod, DexString> additionalMethodNamings = Maps.newIdentityHashMap();
private final Map<DexField, DexString> additionalFieldNamings = Maps.newIdentityHashMap();
@@ -135,7 +136,7 @@
new MethodNameMinifier(appView, nameStrategy)
.computeRenaming(interfaces, subtypingInfo, executorService, timing);
// Amend the method renamings with the default interface methods.
- methodRenaming.renaming.putAll(defaultInterfaceMethodImplementationNames);
+ methodRenaming.renaming.putAll(companionClassInterfaceMethodImplementationNames);
methodRenaming.renaming.putAll(additionalMethodNamings);
timing.end();
@@ -329,19 +330,16 @@
// TODO(b/150736225): Is this sound? What if the type is a library type that has been pruned?
DexClass dexClass = appView.appInfo().definitionForWithoutExistenceAssert(type);
if (dexClass == null || dexClass.isClasspathClass()) {
- computeDefaultInterfaceMethodMappingsForType(
- type,
- classNaming,
- defaultInterfaceMethodImplementationNames);
+ computeCompanionClassInterfaceMethodMappingsForType(
+ type, classNaming, companionClassInterfaceMethodImplementationNames);
}
}
}
- @SuppressWarnings("ReferenceEquality")
- private void computeDefaultInterfaceMethodMappingsForType(
+ private void computeCompanionClassInterfaceMethodMappingsForType(
DexType type,
ClassNamingForMapApplier classNaming,
- Map<DexMethod, DexString> defaultInterfaceMethodImplementationNames) {
+ Map<DexMethod, DexString> companionClassInterfaceMethodImplementationNames) {
// If the class does not resolve, then check if it is a companion class for an interface on
// the class path.
if (!isCompanionClassType(type)) {
@@ -360,12 +358,26 @@
MemberNaming naming = namings.get(0);
MethodSignature signature = (MethodSignature) naming.getOriginalSignature();
if (signature.name.startsWith(interfaceType.type.toSourceString())) {
- DexMethod defaultMethod =
- defaultAsMethodOfCompanionClass(
- signature.toUnqualified().toDexMethod(factory, interfaceType.type), factory);
- assert defaultMethod.holder == type;
- defaultInterfaceMethodImplementationNames.put(
- defaultMethod, factory.createString(naming.getRenamedName()));
+ DexMethod originalReference =
+ signature.toUnqualified().toDexMethod(factory, interfaceType.type);
+ DexEncodedMethod originalDefinition = interfaceType.lookupMethod(originalReference);
+ if (originalDefinition == null) {
+ assert false;
+ continue;
+ }
+ DexMethod originalDesugaredMethod;
+ if (originalDefinition.isStatic()) {
+ originalDesugaredMethod = staticAsMethodOfCompanionClass(originalReference, factory);
+ } else if (originalDefinition.isNonAbstractVirtualMethod()) {
+ originalDesugaredMethod = defaultAsMethodOfCompanionClass(originalReference, factory);
+ } else {
+ // There is no implementation for private interface methods as those are not accessible
+ // outside the interface itself and should never need to be represented for apply mapping.
+ continue;
+ }
+ assert type.isIdenticalTo(originalDesugaredMethod.holder);
+ DexString renamed = factory.createString(naming.getRenamedName());
+ companionClassInterfaceMethodImplementationNames.put(originalDesugaredMethod, renamed);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/accessmodification/AccessModifier.java b/src/main/java/com/android/tools/r8/optimize/accessmodification/AccessModifier.java
index fba2f6f..c97f10b 100644
--- a/src/main/java/com/android/tools/r8/optimize/accessmodification/AccessModifier.java
+++ b/src/main/java/com/android/tools/r8/optimize/accessmodification/AccessModifier.java
@@ -317,7 +317,10 @@
lensBuilder.recordMove(method.getReference(), newMethodReference);
method =
new ProgramMethod(
- holder, method.getDefinition().toTypeSubstitutedMethod(newMethodReference));
+ holder,
+ method
+ .getDefinition()
+ .toTypeSubstitutedMethodAsInlining(newMethodReference, appView.dexItemFactory()));
}
if (method.getAccessFlags().isPromotedFromPrivateToPublic()
&& method.getAccessFlags().belongsToVirtualPool()) {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorApplicationFixer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorApplicationFixer.java
index 12a71ce..3d7c4e6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorApplicationFixer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorApplicationFixer.java
@@ -102,8 +102,9 @@
}
DexEncodedMethod replacement =
- method.toTypeSubstitutedMethod(
+ method.toTypeSubstitutedMethodAsInlining(
methodReferenceAfterParameterRemoval,
+ appView.dexItemFactory(),
builder -> {
if (graphLens.hasPrototypeChanges(methodReferenceAfterParameterRemoval)) {
RewrittenPrototypeDescription prototypeChanges =
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
index d8149d7..387d67d 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
@@ -263,7 +263,9 @@
DexMethod newMethodReference =
appView.dexItemFactory().createMethod(clazz.type, method.proto, method.name);
DexEncodedMethod newMethod =
- representative.getDefinition().toTypeSubstitutedMethod(newMethodReference);
+ representative
+ .getDefinition()
+ .toTypeSubstitutedMethodAsInlining(newMethodReference, appView.dexItemFactory());
if (newMethod.getAccessFlags().isFinal()) {
newMethod.getAccessFlags().demoteFromFinal();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java
index 3cac2b3..902fb45 100644
--- a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java
@@ -136,8 +136,9 @@
// this should simply clear the optimization info, or replace it by a
// ThrowingMethodOptimizationInfo since we should never use the optimization
// info after this point.
- return method.toTypeSubstitutedMethod(
+ return method.toTypeSubstitutedMethodAsInlining(
newMethodReference,
+ dexItemFactory,
builder -> {
if (!prototypeChanges.isEmpty()) {
builder
diff --git a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
index 1b9b6c3..55501d8 100644
--- a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
+++ b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.InnerClassAttribute;
@@ -115,6 +116,11 @@
protected boolean isLegitimateToHaveEmptyMappings() {
return true;
}
+
+ @Override
+ public <T extends DexReference> boolean isSimpleRenaming(T from, T to) {
+ return getPrevious().isSimpleRenaming(from, to);
+ }
};
DirectMappedDexApplication newApplication =
appView
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 0f3b284..1b2114d 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -67,7 +67,6 @@
import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.InvokeType;
-import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
@@ -1014,7 +1013,9 @@
virtualMethod.getProto().prependParameter(source.getType(), dexItemFactory),
dexItemFactory.createGloballyFreshMemberString(resultingMethodBaseName));
assert availableMethodSignatures.test(resultingMethodReference);
- resultingMethod = virtualMethod.toTypeSubstitutedMethod(resultingMethodReference);
+ resultingMethod =
+ virtualMethod.toTypeSubstitutedMethodAsInlining(
+ resultingMethodReference, dexItemFactory);
makeStatic(resultingMethod);
} else {
// This virtual method could be called directly from a sub class via an invoke-super in-
@@ -1443,7 +1444,6 @@
SynthesizedBridgeCode code =
new SynthesizedBridgeCode(
newMethod,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
invocationTarget.getReference(),
invocationTarget.isStatic()
? STATIC
@@ -1562,7 +1562,8 @@
count++;
} while (!availableMethodSignatures.test(newSignature));
- DexEncodedMethod result = method.toTypeSubstitutedMethod(newSignature);
+ DexEncodedMethod result =
+ method.toTypeSubstitutedMethodAsInlining(newSignature, appView.dexItemFactory());
result.getMutableOptimizationInfo().markForceInline();
deferredRenamings.map(method.getReference(), result.getReference());
deferredRenamings.recordMove(method.getReference(), result.getReference());
@@ -1616,7 +1617,7 @@
throw new Unreachable();
}
- return method.toTypeSubstitutedMethod(newSignature);
+ return method.toTypeSubstitutedMethodAsInlining(newSignature, appView.dexItemFactory());
}
private DexEncodedField renameFieldIfNeeded(
@@ -2242,22 +2243,19 @@
public void registerTypeReference(DexType type) {}
}
- protected static class SynthesizedBridgeCode extends AbstractSynthesizedCode {
+ public static class SynthesizedBridgeCode extends AbstractSynthesizedCode {
private DexMethod method;
- private DexMethod originalMethod;
private DexMethod invocationTarget;
private InvokeType type;
private final boolean isInterface;
public SynthesizedBridgeCode(
DexMethod method,
- DexMethod originalMethod,
DexMethod invocationTarget,
InvokeType type,
boolean isInterface) {
this.method = method;
- this.originalMethod = originalMethod;
this.invocationTarget = invocationTarget;
this.type = type;
this.isInterface = isInterface;
@@ -2285,20 +2283,12 @@
ForwardMethodSourceCode.builder(method);
forwardSourceCodeBuilder
.setReceiver(method.holder)
- .setOriginalMethod(originalMethod)
.setTargetReceiver(type.isStatic() ? null : method.holder)
.setTarget(invocationTarget)
.setInvokeType(type)
.setIsInterface(isInterface);
return (context, callerPosition) -> {
- SyntheticPosition caller =
- SyntheticPosition.builder()
- .setLine(0)
- .setMethod(method)
- .setIsD8R8Synthesized(true)
- .setCallerPosition(callerPosition)
- .build();
- return forwardSourceCodeBuilder.build(context, caller);
+ return forwardSourceCodeBuilder.build(context, callerPosition);
};
}
diff --git a/src/main/java/com/android/tools/r8/utils/DexDebugUtils.java b/src/main/java/com/android/tools/r8/utils/DexDebugUtils.java
index adfda77..54b8da6 100644
--- a/src/main/java/com/android/tools/r8/utils/DexDebugUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/DexDebugUtils.java
@@ -37,13 +37,13 @@
}
public static PositionInfo computePreamblePosition(
- DexMethod method, EventBasedDebugInfo debugInfo) {
+ DexMethod method, boolean isD8R8Synthesized, EventBasedDebugInfo debugInfo) {
if (debugInfo == null) {
return PositionInfo.builder().build();
}
Box<Position> existingPositionFrame = new Box<>();
DexDebugPositionState visitor =
- new DexDebugPositionState(debugInfo.startLine, method) {
+ new DexDebugPositionState(debugInfo.startLine, method, isD8R8Synthesized) {
@Override
public void visit(SetPositionFrame setPositionFrame) {
super.visit(setPositionFrame);
diff --git a/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java b/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java
index 787dd32..08d30ac 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java
@@ -70,17 +70,20 @@
// If a method with overloads does not have an actual position then map it to the implicit
// preamble position.
DexMethod reference = method.getReference();
- DexMethod original = appView.graphLens().getOriginalMethodSignature(reference);
CfPosition preamblePositionForOverload =
new CfPosition(
new CfLabel(),
remapAndAdd(
- SyntheticPosition.builder().setMethod(original).setLine(0).build(),
+ SyntheticPosition.builder()
+ .setMethod(reference)
+ .setLine(0)
+ .setIsD8R8Synthesized(method.getDefinition().isD8R8Synthesized())
+ .build(),
positionRemapper,
mappedPositions));
List<CfInstruction> shiftedPositions = new ArrayList<>(oldInstructions.size() + 2);
- shiftedPositions.add(preamblePositionForOverload);
shiftedPositions.add(preamblePositionForOverload.getLabel());
+ shiftedPositions.add(preamblePositionForOverload);
shiftedPositions.addAll(newInstructions);
newInstructions = shiftedPositions;
}
diff --git a/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java b/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java
index 8e0fcbb..099e233 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java
@@ -99,8 +99,9 @@
List<DexDebugEvent> processedEvents,
DexItemFactory factory,
int startLine,
- DexMethod method) {
- super(startLine, method);
+ DexMethod method,
+ boolean isD8R8Synthesized) {
+ super(startLine, method, isD8R8Synthesized);
this.positionEventEmitter = positionEventEmitter;
this.mappedPositions = mappedPositions;
this.positionRemapper = positionRemapper;
@@ -189,12 +190,9 @@
getEventBasedDebugInfo(method.getDefinition(), dexCode, appView);
List<DexDebugEvent> processedEvents = new ArrayList<>();
-
PositionEventEmitter positionEventEmitter =
new PositionEventEmitter(
- application.dexItemFactory,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- processedEvents);
+ application.dexItemFactory, method.getReference(), processedEvents);
DexDebugPositionStateVisitor visitor =
new DexDebugPositionStateVisitor(
@@ -204,7 +202,8 @@
processedEvents,
appView.dexItemFactory(),
debugInfo.startLine,
- appView.graphLens().getOriginalMethodSignature(method.getReference()));
+ method.getReference(),
+ method.getDefinition().isD8R8Synthesized());
DexDebugEvent[] events = debugInfo.events;
for (DexDebugEvent event : events) {
@@ -219,7 +218,7 @@
assert !isIdentityMapping
|| visitor.inlinedOriginalPosition
- || verifyIdentityMapping(debugInfo, optimizedDebugInfo);
+ || verifyIdentityMapping(method, debugInfo, optimizedDebugInfo);
dexCode.setDebugInfo(optimizedDebugInfo);
return mappedPositions;
@@ -242,7 +241,12 @@
}
private static boolean verifyIdentityMapping(
- EventBasedDebugInfo originalDebugInfo, EventBasedDebugInfo optimizedDebugInfo) {
+ ProgramMethod method,
+ EventBasedDebugInfo originalDebugInfo,
+ EventBasedDebugInfo optimizedDebugInfo) {
+ if (isTrivialSyntheticMethod(method, originalDebugInfo)) {
+ return true;
+ }
assert optimizedDebugInfo.startLine == originalDebugInfo.startLine;
assert optimizedDebugInfo.events.length == originalDebugInfo.events.length;
for (int i = 0; i < originalDebugInfo.events.length; ++i) {
@@ -250,4 +254,27 @@
}
return true;
}
+
+ private static boolean isTrivialSyntheticMethod(
+ ProgramMethod method, EventBasedDebugInfo originalDebugInfo) {
+ if (!method.getDefinition().isD8R8Synthesized()) {
+ return false;
+ }
+ // A synthetic method may have different debug info but still be trivial if it holds that all
+ // the frames are just trivial frames for the synthetic method itself.
+ for (DexDebugEvent event : originalDebugInfo.events) {
+ if (event.isPositionFrame()) {
+ Position position = event.asSetPositionFrame().getPosition();
+ if (!method.getReference().isIdenticalTo(position.getMethod())
+ || !position.isD8R8Synthesized()
+ || position.hasCallerPosition()
+ || position.isOutline()
+ || position.isRemoveInnerFramesIfThrowingNpe()) {
+ // If the frame is not trivial then break and assert the usual identity property.
+ return false;
+ }
+ }
+ }
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/positions/DexPositionToPcMappedRangeMapper.java b/src/main/java/com/android/tools/r8/utils/positions/DexPositionToPcMappedRangeMapper.java
index ecc6468..a1bb8a5 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/DexPositionToPcMappedRangeMapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/DexPositionToPcMappedRangeMapper.java
@@ -45,7 +45,8 @@
DexDebugEventVisitor visitor =
new DexDebugPositionState(
debugInfo.startLine,
- appView.graphLens().getOriginalMethodSignature(method.getReference())) {
+ method.getReference(),
+ method.getDefinition().isD8R8Synthesized()) {
@Override
public void visit(Default defaultEvent) {
super.visit(defaultEvent);
diff --git a/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java
index c91839c..12a6f21 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java
@@ -147,9 +147,7 @@
for (ProgramMethod method : methods) {
DexEncodedMethod definition = method.getDefinition();
- DexMethod methodReference = method.getReference();
if (methodName == method.getName()
- && appView.graphLens().getOriginalMethodSignature(methodReference) == methodReference
&& !mustHaveResidualDebugInfo(appView.options(), definition)
&& !definition.isD8R8Synthesized()
&& methods.size() <= 1) {
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 41a3ecc..80e22b5 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
@@ -18,6 +18,7 @@
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.ir.code.Position.OutlinePosition;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.ClassNaming;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
@@ -224,10 +225,6 @@
PositionRemapper positionRemapper,
boolean canUseDexPc) {
DexEncodedMethod definition = method.getDefinition();
- DexMethod originalMethod =
- appView.graphLens().getOriginalMethodSignatureForMapping(method.getReference());
- MethodSignature originalSignature =
- MethodSignature.fromDexMethod(originalMethod, originalMethod.holder != originalType);
OneShotCollectionConsumer<MappingInformation> methodSpecificMappingInformation =
OneShotCollectionConsumer.wrap(new ArrayList<>());
@@ -236,13 +233,25 @@
// classes in the library. Additionally, this is one place where it is helpful for developers
// to also get reported synthesized frames since stubbing can change control-flow and
// exceptions.
- if (isD8R8Synthesized(method, mappedPositions)
- && !appView.getSyntheticItems().isGlobalSyntheticClass(method.getHolder())) {
+ boolean canStripOuterFrame = canStripOuterFrame(method, mappedPositions);
+ boolean residualIsD8R8Synthesized =
+ method.getDefinition().isD8R8Synthesized()
+ && !appView.getSyntheticItems().isGlobalSyntheticClass(method.getHolder())
+ // TODO(b/302509457): Currently we can only represent moves on methods that have code
+ // and thus positions. For methods with no code, use the lens to find the original.
+ && method.getDefinition().hasCode();
+ if (residualIsD8R8Synthesized && !canStripOuterFrame) {
methodSpecificMappingInformation.add(CompilerSynthesizedMappingInformation.getInstance());
}
DexMethod residualMethod =
appView.getNamingLens().lookupMethod(method.getReference(), appView.dexItemFactory());
+ MethodSignature residualSignature = MethodSignature.fromDexMethod(residualMethod);
+
+ DexMethod originalMethod =
+ appView.graphLens().getOriginalMethodSignatureForMapping(method.getReference());
+ MethodSignature originalSignature =
+ MethodSignature.fromDexMethod(originalMethod, originalMethod.holder != originalType);
MapVersion mapFileVersion = appView.options().getMapFileVersion();
if (isIdentityMapping(
@@ -257,13 +266,32 @@
|| appView.isCfByteCodePassThrough(definition);
return this;
}
- MethodSignature residualSignature = MethodSignature.fromDexMethod(residualMethod);
- if (ResidualSignatureMappingInformation.isSupported(mapFileVersion)
- && (!originalSignature.type.equals(residualSignature.type)
- || !Arrays.equals(originalSignature.parameters, residualSignature.parameters))) {
- methodSpecificMappingInformation.add(
- ResidualMethodSignatureMappingInformation.fromDexMethod(residualMethod));
+ if (ResidualSignatureMappingInformation.isSupported(mapFileVersion)) {
+ boolean isSame = true;
+ if (canStripOuterFrame) {
+ for (MappedPosition mappedPosition : mappedPositions) {
+ Position outerMostAfterStrip = mappedPosition.getPosition();
+ while (outerMostAfterStrip.getCallerPosition().hasCallerPosition()) {
+ outerMostAfterStrip = outerMostAfterStrip.getCallerPosition();
+ }
+ MethodSignature positionSignature =
+ MethodSignature.fromDexMethod(outerMostAfterStrip.getMethod());
+ if (!positionSignature.type.equals(residualSignature.type)
+ || !Arrays.equals(positionSignature.parameters, residualSignature.parameters)) {
+ isSame = false;
+ break;
+ }
+ }
+ } else {
+ isSame =
+ originalSignature.type.equals(residualSignature.type)
+ && Arrays.equals(originalSignature.parameters, residualSignature.parameters);
+ }
+ if (!isSame) {
+ methodSpecificMappingInformation.add(
+ ResidualMethodSignatureMappingInformation.fromDexMethod(residualMethod));
+ }
}
MemberNaming memberNaming = new MemberNaming(originalSignature, residualSignature);
@@ -293,11 +321,11 @@
});
// Check if mapped position is an outline
- DexMethod outlineMethod = getOutlineMethod(mappedPositions.get(0).getPosition());
- if (outlineMethod != null) {
+ DexMethod outlineMethodKey = getOutlineMethodKey(mappedPositions);
+ if (outlineMethodKey != null) {
outlinesToFix
.computeIfAbsent(
- outlineMethod,
+ outlineMethodKey,
outline -> new OutlineFixupBuilder(computeMappedMethod(outline, appView)))
.setMappedPositionsOutline(mappedPositions);
methodSpecificMappingInformation.add(OutlineMappingInformation.builder().build());
@@ -348,6 +376,11 @@
Range originalRange =
nonCardinalRangeCache.get(firstPosition.getLine(), lastPosition.getLine());
+ boolean hasSyntheticOuterFrameAndNonSyntheticInner =
+ residualIsD8R8Synthesized && firstPosition.hasCallerPosition();
+ assert !hasSyntheticOuterFrameAndNonSyntheticInner
+ || firstPosition.getOutermostCaller().isD8R8Synthesized();
+
MappedRange lastMappedRange =
getMappedRangesForPosition(
appView,
@@ -358,7 +391,8 @@
obfuscatedRange,
originalRange,
prunedInlinedClasses,
- cardinalRangeCache);
+ cardinalRangeCache,
+ canStripOuterFrame);
// firstPosition will contain a potential outline caller.
if (firstPosition.isOutlineCaller()) {
outlineCallerPositions.putIfAbsent(firstPosition.asOutlineCaller(), lastMappedRange);
@@ -395,7 +429,8 @@
placeHolderLineToBeFixed, placeHolderLineToBeFixed),
nonCardinalRangeCache.get(position.getLine(), position.getLine()),
prunedInlinedClasses,
- cardinalRangeCache);
+ cardinalRangeCache,
+ canStripOuterFrame);
maxPc.set(lastRange.minifiedRange.to);
});
outlinesToFix
@@ -409,10 +444,40 @@
return this;
}
- private boolean isD8R8Synthesized(ProgramMethod method, List<MappedPosition> mappedPositions) {
- return method.getDefinition().isD8R8Synthesized()
- || (!mappedPositions.isEmpty()
- && mappedPositions.get(0).getPosition().isD8R8Synthesized());
+ private boolean canStripOuterFrame(ProgramMethod method, List<MappedPosition> mappedPositions) {
+ assert verifySyntheticPositions(method, mappedPositions);
+ if (!method.getDefinition().isD8R8Synthesized() || mappedPositions.isEmpty()) {
+ return false;
+ }
+ for (MappedPosition mappedPosition : mappedPositions) {
+ Position position = mappedPosition.getPosition();
+ if (!position.hasCallerPosition()) {
+ // At least one position only has the synthetic method as its frame, so we can't strip it.
+ return false;
+ }
+ if (position.isOutline() || position.isOutlineCaller()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean verifySyntheticPositions(
+ ProgramMethod method, List<MappedPosition> mappedPositions) {
+ DexMethod thisMethod = method.getReference();
+ boolean d8R8Synthesized = method.getDefinition().isD8R8Synthesized();
+ for (MappedPosition mappedPosition : mappedPositions) {
+ Position position = mappedPosition.getPosition();
+ while (position.hasCallerPosition()) {
+ assert !position.isOutline();
+ assert !position.isD8R8Synthesized();
+ position = position.getCallerPosition();
+ }
+ DexMethod outerCaller = position.getMethod();
+ assert thisMethod.isIdenticalTo(outerCaller);
+ assert d8R8Synthesized == position.isD8R8Synthesized();
+ }
+ return true;
}
private MethodReference computeMappedMethod(DexMethod current, AppView<?> appView) {
@@ -432,13 +497,15 @@
Range obfuscatedRange,
Range originalLine,
Map<DexType, String> prunedInlineHolder,
- CardinalPositionRangeAllocator cardinalRangeCache) {
+ CardinalPositionRangeAllocator cardinalRangeCache,
+ boolean canStripOuterFrame) {
MappedRange lastMappedRange = null;
int inlineFramesCount = -1;
do {
- if (position.isD8R8Synthesized() && position.hasCallerPosition()) {
- position = position.getCallerPosition();
- continue;
+ if (canStripOuterFrame && !position.hasCallerPosition()) {
+ assert position.isD8R8Synthesized();
+ assert lastMappedRange != null;
+ break;
}
inlineFramesCount += 1;
DexType holderType = position.getMethod().getHolderType();
@@ -473,16 +540,15 @@
return lastMappedRange;
}
- private DexMethod getOutlineMethod(Position mappedPosition) {
- if (mappedPosition.isOutline()) {
- return mappedPosition.getMethod();
+ private DexMethod getOutlineMethodKey(List<MappedPosition> mappedPositions) {
+ for (MappedPosition mappedPosition : mappedPositions) {
+ Position position = mappedPosition.getPosition().getOutermostCaller();
+ if (position.isOutline()) {
+ OutlinePosition outline = (OutlinePosition) position;
+ return outline.getOutlineMethodKey();
+ }
}
- Position caller = mappedPosition.getCallerPosition();
- if (caller == null) {
- return null;
- }
- Position outermostCaller = caller.getOutermostCaller();
- return outermostCaller.isOutline() ? outermostCaller.getMethod() : null;
+ return null;
}
@SuppressWarnings("ReferenceEquality")
diff --git a/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java b/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java
index 1d7e99f..4026dc3 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java
@@ -77,10 +77,9 @@
}
@Override
- @SuppressWarnings("ReferenceEquality")
public Pair<Position, Position> createRemappedPosition(Position position) {
assert position.getMethod() != null;
- if (previousMethod == position.getMethod()) {
+ if (position.getMethod().isIdenticalTo(previousMethod)) {
assert previousSourceLine >= 0;
if (position.getLine() > previousSourceLine
&& position.getLine() - previousSourceLine <= maxLineDelta) {
diff --git a/src/test/examples/shaking1/print-mapping-cf.ref b/src/test/examples/shaking1/print-mapping-cf.ref
deleted file mode 100644
index 8b38084..0000000
--- a/src/test/examples/shaking1/print-mapping-cf.ref
+++ /dev/null
@@ -1,7 +0,0 @@
-shaking1.Shaking -> shaking1.Shaking:
-shaking1.Used -> a.a:
- 1:2:void <init>(java.lang.String):12:13 -> <init>
- 1:1:java.lang.String aMethodThatIsNotUsedButKept():21:21 -> aMethodThatIsNotUsedButKept
- 1:2:void main(java.lang.String[]):8:9 -> main
- 1:1:java.lang.String method():17:17 -> a
- java.lang.String name -> a
\ No newline at end of file
diff --git a/src/test/examples/shaking1/print-mapping-dex.ref b/src/test/examples/shaking1/print-mapping-dex.ref
deleted file mode 100644
index cd0d3a3..0000000
--- a/src/test/examples/shaking1/print-mapping-dex.ref
+++ /dev/null
@@ -1,8 +0,0 @@
-shaking1.Shaking -> shaking1.Shaking:
- 0:8:void main(java.lang.String[]):8:8 -> main
- 9:21:void main(java.lang.String[]):9:9 -> main
-shaking1.Used -> a.a:
- java.lang.String name -> a
- 0:5:void <init>(java.lang.String):12:12 -> <init>
- 0:16:java.lang.String method():17:17 -> a
- 0:2:java.lang.String aMethodThatIsNotUsedButKept():0:0 -> aMethodThatIsNotUsedButKept
diff --git a/src/test/java/com/android/tools/r8/R8EntryPointTests.java b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
index c0b143c..72438ac 100644
--- a/src/test/java/com/android/tools/r8/R8EntryPointTests.java
+++ b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
@@ -19,7 +19,11 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class R8EntryPointTests extends TestBase {
private static final String MAPPING = "mapping.txt";
@@ -31,6 +35,15 @@
private Path testFlags;
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return TestParameters.builder().withNoneRuntime().build();
+ }
+
+ public R8EntryPointTests(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
@Before
public void setup() throws IOException {
testFlags = temp.newFile("local.flags").toPath();
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java
index 57e100b..e88c86e 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java
@@ -43,14 +43,14 @@
ClassSubject bClassSubject = codeInspector.clazz(B.class);
assertThat(bClassSubject, isPresent());
- methodSubject = bClassSubject.method("void", "foo$bridge");
+ methodSubject = getUniqueDispatchBridgeMethod(bClassSubject);
assertThat(methodSubject, isPackagePrivate());
assertThat(codeInspector.clazz(C.class), isAbsent());
ClassSubject dClassSubject = codeInspector.clazz(D.class);
assertThat(dClassSubject, isPresent());
- methodSubject = dClassSubject.method("void", "foo$bridge");
+ methodSubject = getUniqueDispatchBridgeMethod(dClassSubject);
assertThat(methodSubject, isPublic());
ClassSubject eClassSubject = codeInspector.clazz(E.class);
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java
index e7723fd..7dee4de 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java
@@ -49,7 +49,7 @@
assertThat(otherInitSubject, isPresent());
assertThat(otherInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
- MethodSubject printSubject = aClassSubject.method("void", "print$bridge");
+ MethodSubject printSubject = getUniqueDispatchBridgeMethod(aClassSubject);
assertThat(printSubject, isPresent());
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
index 9288d9b..ac23576 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
@@ -61,7 +61,7 @@
assertThat(otherInitSubject, isPresent());
assertThat(otherInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
- MethodSubject printSubject = aClassSubject.method("void", "print$bridge");
+ MethodSubject printSubject = getUniqueDispatchBridgeMethod(aClassSubject);
assertThat(printSubject, isPresent());
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java
index ba27f46..2be25d3 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java
@@ -49,7 +49,7 @@
assertThat(otherInitSubject, isPresent());
assertThat(otherInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
- MethodSubject printSubject = aClassSubject.method("void", "print$bridge");
+ MethodSubject printSubject = getUniqueDispatchBridgeMethod(aClassSubject);
assertThat(printSubject, isPresent());
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
index a24aca6..0c564bc 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.horizontalclassmerging.ClassMerger;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -29,6 +30,10 @@
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
+ public static MethodSubject getUniqueDispatchBridgeMethod(ClassSubject clazz) {
+ return clazz.uniqueMethodThatMatches(m -> m.isVirtual() && m.isCompilerSynthesized());
+ }
+
protected FieldSubject classMergerClassIdField(ClassSubject classSubject) {
assertTrue(classSubject.isPresent());
FieldSubject[] classIds =
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
index 915e10b..4f7faad 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
@@ -51,7 +51,7 @@
assertThat(otherInitSubject, isPresent());
assertThat(otherInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
- MethodSubject printSubject = aClassSubject.method("void", "print$bridge");
+ MethodSubject printSubject = getUniqueDispatchBridgeMethod(aClassSubject);
assertThat(printSubject, isPresent());
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorWithEquivalenceStackTraceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorWithEquivalenceStackTraceTest.java
index 655e6a8..3126419 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorWithEquivalenceStackTraceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorWithEquivalenceStackTraceTest.java
@@ -4,36 +4,87 @@
package com.android.tools.r8.classmerging.horizontal;
-import static com.android.tools.r8.naming.retrace.StackTrace.isSame;
+import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForLineNumbers;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertTrue;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.naming.retrace.StackTrace;
-import org.junit.BeforeClass;
+import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
import org.junit.Test;
public class MergedConstructorWithEquivalenceStackTraceTest extends HorizontalClassMergingTestBase {
- private static StackTrace expectedStackTrace;
-
public MergedConstructorWithEquivalenceStackTraceTest(TestParameters parameters) {
super(parameters);
}
- @BeforeClass
- public static void setup() throws Exception {
+ private final String FILE_NAME =
+ ToolHelper.getSourceFileForTestClass(getClass()).getFileName().toString();
+
+ private StackTrace getExpectedStackTrace() {
+ return StackTrace.builder()
+ .add(
+ StackTraceLine.builder()
+ .setFileName(FILE_NAME)
+ .setClassName(typeName(Parent.class))
+ .setMethodName("<init>")
+ .build())
+ .add(
+ StackTraceLine.builder()
+ .setFileName(FILE_NAME)
+ .setClassName(typeName(A.class))
+ .setMethodName("<init>")
+ .build())
+ .add(
+ StackTraceLine.builder()
+ .setFileName(FILE_NAME)
+ .setClassName(typeName(Main.class))
+ .setMethodName("main")
+ .build())
+ .build();
+ }
+
+ // TODO(b/301920457): The constructors should be merged in such a way that the original stack can
+ // be recovered.
+ private StackTrace getUnxpectedStackTrace() {
+ return StackTrace.builder()
+ .add(
+ StackTraceLine.builder()
+ .setFileName(FILE_NAME)
+ .setClassName(typeName(Parent.class))
+ .setMethodName("<init>")
+ .build())
+ .add(
+ StackTraceLine.builder()
+ .setFileName(FILE_NAME)
+ .setClassName(typeName(Main.class))
+ .setMethodName("main")
+ .build())
+ .build();
+ }
+
+ private void checkRetracedStackTrace(StackTrace expectedStackTrace, StackTrace stackTrace) {
+ assertThat(stackTrace, isSameExceptForLineNumbers(expectedStackTrace));
+ for (StackTraceLine line : stackTrace.getStackTraceLines()) {
+ assertTrue(line.lineNumber > 0);
+ }
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ parameters.assumeJvmTestParameters();
// Get the expected stack trace by running on the JVM.
- expectedStackTrace =
- testForJvm(getStaticTemp())
- .addTestClasspath()
- .run(CfRuntime.getSystemRuntime(), Main.class)
- .assertFailure()
- .map(StackTrace::extractFromJvm);
+ testForJvm(parameters)
+ .addTestClasspath()
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailure()
+ .inspectStackTrace(actual -> checkRetracedStackTrace(getExpectedStackTrace(), actual));
}
@Test
@@ -54,17 +105,8 @@
.inspectStackTrace(
(stackTrace, codeInspector) -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- StackTrace expectedStackTraceWithMergedConstructor =
- StackTrace.builder()
- .add(expectedStackTrace)
- // TODO(b/124483578): Stack trace lines from the merging of equivalent
- // constructors should retrace to the set of lines from each of the
- // individual source constructors.
- .map(
- 1, stackTraceLine -> stackTraceLine.builderOf().setLineNumber(-1).build())
- .build();
- assertThat(stackTrace, isSame(expectedStackTraceWithMergedConstructor));
assertThat(codeInspector.clazz(B.class), not(isPresent()));
+ checkRetracedStackTrace(getUnxpectedStackTrace(), stackTrace);
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodNonTrivialMergeTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodNonTrivialMergeTest.java
index 478958e..625af3f 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodNonTrivialMergeTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodNonTrivialMergeTest.java
@@ -47,7 +47,7 @@
ClassSubject classSubject = inspector.clazz(A.class);
assertThat(classSubject, isPresent());
- MethodSubject methodSubject = classSubject.uniqueMethodWithOriginalName("foo$bridge");
+ MethodSubject methodSubject = getUniqueDispatchBridgeMethod(classSubject);
assertThat(methodSubject, isPresent());
assertFalse(methodSubject.isFinal());
})
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonPublicOverrideOfPublicMethodAfterClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonPublicOverrideOfPublicMethodAfterClassMergingTest.java
index 1edbf47..33a04c3 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonPublicOverrideOfPublicMethodAfterClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonPublicOverrideOfPublicMethodAfterClassMergingTest.java
@@ -59,7 +59,8 @@
ClassSubject iClassSubject = inspector.clazz(I.class);
assertThat(iClassSubject, isPresent());
assertThat(
- iClassSubject.uniqueMethodWithOriginalName("m"), allOf(isPresent(), isPublic()));
+ iClassSubject.uniqueMethodThatMatches(m -> !m.isInstanceInitializer()),
+ allOf(isPresent(), isPublic()));
ClassSubject aClassSubject = inspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java
index 0b644b8..834f76d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java
@@ -47,7 +47,7 @@
assertThat(aClassSubject, isPresent());
MethodSubject synchronizedMethodSubject =
- aClassSubject.uniqueMethodWithOriginalName("m$bridge");
+ getUniqueDispatchBridgeMethod(aClassSubject);
assertThat(synchronizedMethodSubject, isPresent());
assertTrue(synchronizedMethodSubject.getAccessFlags().isStrict());
@@ -55,7 +55,7 @@
assertThat(cClassSubject, isPresent());
MethodSubject unsynchronizedMethodSubject =
- cClassSubject.uniqueMethodWithOriginalName("m$bridge");
+ getUniqueDispatchBridgeMethod(cClassSubject);
assertThat(unsynchronizedMethodSubject, isPresent());
assertFalse(unsynchronizedMethodSubject.getAccessFlags().isStrict());
})
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java
index dd93d69..9eeea86 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java
@@ -47,7 +47,7 @@
assertThat(aClassSubject, isPresent());
MethodSubject synchronizedMethodSubject =
- aClassSubject.uniqueMethodWithOriginalName("m$bridge");
+ getUniqueDispatchBridgeMethod(aClassSubject);
assertThat(synchronizedMethodSubject, isPresent());
assertTrue(synchronizedMethodSubject.isSynchronized());
@@ -55,7 +55,7 @@
assertThat(cClassSubject, isPresent());
MethodSubject unsynchronizedMethodSubject =
- cClassSubject.uniqueMethodWithOriginalName("m$bridge");
+ getUniqueDispatchBridgeMethod(cClassSubject);
assertThat(unsynchronizedMethodSubject, isPresent());
assertFalse(unsynchronizedMethodSubject.isSynchronized());
})
diff --git a/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java b/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java
index 851d489..29d8d11 100644
--- a/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java
@@ -32,7 +32,6 @@
"lambda$main$1(" + fileName + ")",
"main(" + fileName + ")");
- // TODO(b/187491007): The "call" frame should have a file name.
static final String EXPECTED_D8 =
StringUtils.lines(
"getStacktraceWithFileNames(" + fileName + ")",
@@ -44,17 +43,6 @@
"call(D8$$SyntheticClass)",
"main(" + fileName + ")");
- static final String EXPECTED_D8_ANDROID_O =
- StringUtils.lines(
- "getStacktraceWithFileNames(" + fileName + ")",
- "lambda$main$0(" + fileName + ")",
- "call(NULL)",
- "main(" + fileName + ")",
- "getStacktraceWithFileNames(" + fileName + ")",
- "lambda$main$1(" + fileName + ")",
- "call(NULL)",
- "main(" + fileName + ")");
-
private final TestParameters parameters;
private final boolean isAndroidOOrLater;
private final boolean isDalvik;
@@ -88,7 +76,7 @@
.addInnerClasses(LambdaInStacktraceTest.class)
.setMinApi(parameters)
.run(parameters.getRuntime(), TestRunner.class, Boolean.toString(isDalvik))
- .assertSuccessWithOutput(isAndroidOOrLater ? EXPECTED_D8_ANDROID_O : EXPECTED_D8);
+ .assertSuccessWithOutput(EXPECTED_D8);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java b/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java
index 909c083..a6cc50b 100644
--- a/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java
+++ b/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java
@@ -80,7 +80,7 @@
.dexItemFactory()
.createMethod(Reference.methodFromDescriptor("LFoo;", "bar", "()V"));
LirCode<?> code =
- LirCode.builder(method, new ThrowingStrategy(), options)
+ LirCode.builder(method, false, new ThrowingStrategy(), options)
.setMetadata(IRMetadata.unknown())
.addConstNull()
.addConstInt(42)
diff --git a/src/test/java/com/android/tools/r8/profile/art/completeness/InvokeSpecialToVirtualMethodProfileRewritingTest.java b/src/test/java/com/android/tools/r8/profile/art/completeness/InvokeSpecialToVirtualMethodProfileRewritingTest.java
index 1f7da5f..a1c6307 100644
--- a/src/test/java/com/android/tools/r8/profile/art/completeness/InvokeSpecialToVirtualMethodProfileRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/profile/art/completeness/InvokeSpecialToVirtualMethodProfileRewritingTest.java
@@ -4,10 +4,11 @@
package com.android.tools.r8.profile.art.completeness;
+import static com.android.tools.r8.synthesis.SyntheticItemsTestUtils.syntheticInvokeSpecialMethod;
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.isInvokeWithTarget;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -15,13 +16,15 @@
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.InternalOptions.InlinerOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.android.tools.r8.utils.codeinspector.CodeMatchers;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -104,20 +107,28 @@
private void inspect(ArtProfileInspector profileInspector, CodeInspector inspector)
throws Exception {
+ Method mMethod = Main.class.getDeclaredMethod("m");
ClassSubject mainClassSubject = inspector.clazz(Main.class);
assertThat(mainClassSubject, isPresent());
- MethodSubject mMethodSubject = mainClassSubject.uniqueMethodWithOriginalName("m");
- assertThat(mMethodSubject, isPresent());
-
- MethodSubject mMovedMethodSubject =
- mainClassSubject.method(
- SyntheticItemsTestUtils.syntheticInvokeSpecialMethod(
- Main.class.getDeclaredMethod("m")));
- assertThat(mMovedMethodSubject, isPresent());
- assertNotEquals(
- mMethodSubject.getProgramMethod().getName(),
- mMovedMethodSubject.getProgramMethod().getName());
+ // Find the two methods named 'm'. Avoid encoding the order and inspect which is the caller.
+ List<FoundMethodSubject> methods =
+ mainClassSubject.allMethods(
+ m -> {
+ String originalName = m.getOriginalName();
+ return originalName.equals("m")
+ || originalName.equals(syntheticInvokeSpecialMethod(mMethod).getMethodName());
+ });
+ assertEquals(2, methods.size());
+ FoundMethodSubject mMethodSubject = methods.get(0);
+ FoundMethodSubject mMovedMethodSubject = methods.get(1);
+ if (!mMethodSubject
+ .streamInstructions()
+ .anyMatch(isInvokeWithTarget(mMovedMethodSubject.getFinalReference()))) {
+ mMethodSubject = methods.get(1);
+ mMovedMethodSubject = methods.get(0);
+ }
+ assertThat(mMethodSubject, CodeMatchers.invokesMethod(mMovedMethodSubject));
// Verify residual profile contains private synthetic method when present.
profileInspector
diff --git a/src/test/java/com/android/tools/r8/profile/art/completeness/MovedPrivateInterfaceMethodProfileRewritingTest.java b/src/test/java/com/android/tools/r8/profile/art/completeness/MovedPrivateInterfaceMethodProfileRewritingTest.java
index 9d36b97..82edb64 100644
--- a/src/test/java/com/android/tools/r8/profile/art/completeness/MovedPrivateInterfaceMethodProfileRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/profile/art/completeness/MovedPrivateInterfaceMethodProfileRewritingTest.java
@@ -132,11 +132,17 @@
inspector.clazz(SyntheticItemsTestUtils.syntheticCompanionClass(I.class));
assertThat(companionClassSubject, isPresent());
+ String mMethodOnI = typeName(I.class) + ".m";
+ String mMethodNameOnICC =
+ SyntheticItemsTestUtils.syntheticPrivateInterfaceMethodAsCompanionMethod(
+ I.class.getDeclaredMethod("m"))
+ .getMethodName();
MethodSubject privateInterfaceMethodSubject =
- companionClassSubject.uniqueMethodWithOriginalName(
- SyntheticItemsTestUtils.syntheticPrivateInterfaceMethodAsCompanionMethod(
- I.class.getDeclaredMethod("m"))
- .getMethodName());
+ companionClassSubject.uniqueMethodThatMatches(
+ m -> {
+ String originalName = m.getOriginalName();
+ return originalName.equals(mMethodOnI) || originalName.equals(mMethodNameOnICC);
+ });
assertThat(privateInterfaceMethodSubject, isPresent());
profileInspector
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
index 8ce1d80..1aaffaf 100644
--- a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
@@ -8,6 +8,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
@@ -152,10 +153,12 @@
CodeInspector inspector = compiled.inspector();
ClassSubject classSubject = inspector.clazz(B.class.getName());
assertThat(classSubject, isPresentAndRenamed());
- assertThat(classSubject.method("void", "m1", ImmutableList.of()), isPresent());
assertThat(classSubject.method("void", "m2", ImmutableList.of()), isAbsent());
assertThat(classSubject.method("void", "m3", ImmutableList.of()), isAbsent());
assertThat(classSubject.method("void", "m4", ImmutableList.of()), isAbsent());
+ assertThat(classSubject.uniqueInstanceInitializer(), isPresent());
+ // The remaining method is the private method corresponding to m1 to ensure IAE.
+ assertEquals(2, classSubject.allMethods().size());
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
index 3f11198..2e03043 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
@@ -15,24 +15,17 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.diagnostic.MissingDefinitionsDiagnostic;
+import com.android.tools.r8.mappingcompose.ComposeTestHelpers;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
-import java.io.BufferedReader;
-import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-@Ignore("Will be fixed by update in CL 84843")
@RunWith(Parameterized.class)
public class TreeShakingSpecificTest extends TestBase {
@@ -94,6 +87,36 @@
});
}
+ private String getExpectedCf() {
+ return StringUtils.lines(
+ "shaking1.Shaking -> shaking1.Shaking:",
+ "# {'id':'sourceFile','fileName':'Shaking.java'}",
+ " 1:2:void main(java.lang.String[]):8:9 -> main",
+ "shaking1.Used -> a.a:",
+ "# {'id':'sourceFile','fileName':'Used.java'}",
+ " java.lang.String name -> a",
+ " 1:14:void <init>(java.lang.String):0:13 -> <init>",
+ " 1:1:java.lang.String method():17:17 -> a",
+ " 1:1:java.lang.String aMethodThatIsNotUsedButKept():21:21 "
+ + "-> aMethodThatIsNotUsedButKept");
+ }
+
+ private String getExpectedDex() {
+ return StringUtils.lines(
+ "shaking1.Shaking -> shaking1.Shaking:",
+ "# {'id':'sourceFile','fileName':'Shaking.java'}",
+ " 0:6:void main(java.lang.String[]):8:8 -> main",
+ " 7:21:void main(java.lang.String[]):9:9 -> main",
+ "shaking1.Used -> a.a:",
+ "# {'id':'sourceFile','fileName':'Used.java'}",
+ " java.lang.String name -> a",
+ " 0:2:void <init>(java.lang.String):12:12 -> <init>",
+ " 3:5:void <init>(java.lang.String):13:13 -> <init>",
+ " 0:16:java.lang.String method():17:17 -> a",
+ " 0:2:java.lang.String aMethodThatIsNotUsedButKept():21:21 "
+ + "-> aMethodThatIsNotUsedButKept");
+ }
+
@Test
public void testPrintMapping() throws Throwable {
// Generate R8 processed version without library option.
@@ -106,25 +129,20 @@
.compile()
.inspectProguardMap(
proguardMap -> {
- // Remove comments.
- String actualMapping =
- Stream.of(proguardMap.split("\n"))
- .filter(line -> !line.startsWith("#"))
- .collect(Collectors.joining("\n"));
- String refMapping =
- new String(
- Files.readAllBytes(
- Paths.get(
- EXAMPLES_DIR,
- "shaking1",
- "print-mapping-" + StringUtils.toLowerCase(backend.name()) + ".ref")),
- StandardCharsets.UTF_8);
- assertEquals(sorted(refMapping), sorted(actualMapping));
+ // Remove header.
+ List<String> lines = StringUtils.splitLines(proguardMap);
+ int firstNonHeaderLine = 0;
+ for (String line : lines) {
+ if (line.startsWith("#")) {
+ firstNonHeaderLine++;
+ } else {
+ break;
+ }
+ }
+ assertEquals(
+ backend.isCf() ? getExpectedCf() : getExpectedDex(),
+ ComposeTestHelpers.doubleToSingleQuote(
+ StringUtils.lines(lines.subList(firstNonHeaderLine, lines.size()))));
});
}
-
- private static String sorted(String str) {
- return new BufferedReader(new StringReader(str))
- .lines().sorted().filter(s -> !s.isEmpty()).collect(Collectors.joining("\n"));
- }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index dc0053b..e7146dc 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -696,4 +696,10 @@
System.out.println(processResult.stdout);
return processResult.stdout;
}
+
+ public MemberNaming getMethodMappingInfo(DexEncodedMethod dexMethod) {
+ return mapping
+ .getNaming()
+ .lookup(MethodSignature.fromDexMethod(dexMethod.getReference(), false));
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index fd18f5a..8cc6ab0 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -340,7 +340,8 @@
}
Object2IntMap<InstructionSubject> lineNumberTable = new Object2IntOpenHashMap<>();
DexDebugPositionState state =
- new DexDebugPositionState(info.startLine, getMethod().getReference());
+ new DexDebugPositionState(
+ info.startLine, getMethod().getReference(), getMethod().isD8R8Synthesized());
Iterator<DexDebugEvent> iterator = Arrays.asList(info.events).iterator();
for (DexInstruction insn : code.instructions) {
int offset = insn.getOffset();
@@ -446,4 +447,10 @@
getDefaultMethodPrefix() + reference.getMethodName(),
p);
}
+
+ @Override
+ public boolean isCompilerSynthesized() {
+ MemberNaming naming = clazz.getMethodMappingInfo(dexMethod);
+ return naming.isCompilerSynthesized();
+ }
}