Merge commit 'afc0a18eecdd0a7cf6e185e73f1ea364ac0d4585' into dev-release
Change-Id: Ic192f94dc9ecec55448e7d5024cef9e05e914407
diff --git a/.gitignore b/.gitignore
index 2fcc852..062fe33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -93,6 +93,8 @@
third_party/dependencies.tar.gz
third_party/dependencies_new/
third_party/dependencies_new.tar.gz
+third_party/dependencies_plugin/
+third_party/dependencies_plugin.tar.gz
third_party/desugar/desugar_*.tar.gz
third_party/desugar/desugar_*/
third_party/examples
diff --git a/d8_r8/main/build.gradle.kts b/d8_r8/main/build.gradle.kts
index 7ce6cc7..47b5da0 100644
--- a/d8_r8/main/build.gradle.kts
+++ b/d8_r8/main/build.gradle.kts
@@ -2,14 +2,25 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import java.net.URI
+import java.nio.file.Path
+import java.nio.file.Paths
+import kotlin.io.path.exists
+import java.nio.file.Files.readString
import net.ltgt.gradle.errorprone.errorprone
+import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import org.spdx.sbom.gradle.SpdxSbomTask
+import org.spdx.sbom.gradle.extensions.DefaultSpdxSbomTaskExtension
+
+import com.google.gson.Gson
plugins {
`kotlin-dsl`
id("dependencies-plugin")
id("net.ltgt.errorprone") version "3.0.1"
+ id("org.spdx.sbom") version "0.2.0-r8-patch01"
}
java {
@@ -35,6 +46,33 @@
errorprone(Deps.errorprone)
}
+if (project.hasProperty("spdxVersion")) {
+ project.version = project.property("spdxVersion")
+}
+
+spdxSbom {
+ targets {
+ create("r8") {
+ // Use of both compileClasspath and runtimeClasspath due to how the
+ // dependencies jar is built and dependencies above therefore use
+ // compileOnly for actual runtime dependencies.
+ configurations.set(listOf("compileClasspath", "runtimeClasspath"))
+ scm {
+ uri.set("https://r8.googlesource.com/r8/")
+ if (project.hasProperty("spdxRevision")) {
+ revision.set(project.property("spdxRevision").toString())
+ }
+ }
+ document {
+ name.set("R8 Compiler Suite")
+ namespace.set("https://r8.googlesource.com/r8/-" + project.version + ".jar")
+ creator.set("Organization: Google LLC")
+ packageSupplier.set("Organization: Google LLC")
+ }
+ }
+ }
+}
+
val keepAnnoJarTask = projectTask("keepanno", "jar")
val resourceShrinkerJarTask = projectTask("resourceshrinker", "jar")
val resourceShrinkerDepsTask = projectTask("resourceshrinker", "depsJar")
@@ -61,6 +99,50 @@
dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
}
+ withType<SpdxSbomTask> {
+ taskExtension.set(object : DefaultSpdxSbomTaskExtension() {
+ override fun mapRepoUri(input: URI?, moduleId: ModuleVersionIdentifier): URI? {
+
+ // Locate the file origin.json with URL for download location.
+ fun getOriginJson() : java.nio.file.Path {
+ var repositoryDir =
+ moduleId.group.replace('.', '/') + "/" + moduleId.name + "/" + moduleId.version
+ val path : Path =
+ Paths.get("third_party", "dependencies", repositoryDir, "origin.json");
+ val path_new : Path =
+ Paths.get("third_party", "dependencies_new", repositoryDir, "origin.json");
+ return if (path.exists()) path else path_new
+ }
+
+ // Simple data model of the content of origin.json generated by the tool to download
+ // and create a local repository. E.g.:
+ /*
+ {
+ "artifacts": [
+ {
+ "file": "org/ow2/asm/asm/9.5/asm-9.5.pom",
+ "repo": "https://repo1.maven.org/maven2/",
+ "artifact": "org.ow2.asm:asm:pom:9.5"
+ },
+ {
+ "file": "org/ow2/asm/asm/9.5/asm-9.5.jar",
+ "repo": "https://repo1.maven.org/maven2/",
+ "artifact": "org.ow2.asm:asm:jar:9.5"
+ }
+ ]
+ }
+ */
+ data class Artifact(val file: String, val repo: String, val artifact: String)
+ data class Artifacts(val artifacts: List<Artifact>)
+
+ // Read origin.json.
+ val json = readString(getOriginJson());
+ val artifacts = Gson().fromJson(json, Artifacts::class.java);
+ return URI.create(artifacts.artifacts.get(0).repo)
+ }
+ })
+ }
+
val consolidatedLicense by registering {
dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
val root = getRoot()
diff --git a/d8_r8/main/settings.gradle.kts b/d8_r8/main/settings.gradle.kts
index 4e1d975..d4f7ab8 100644
--- a/d8_r8/main/settings.gradle.kts
+++ b/d8_r8/main/settings.gradle.kts
@@ -5,7 +5,7 @@
pluginManagement {
repositories {
maven {
- url = uri("file:../../third_party/dependencies")
+ url = uri("file:../../third_party/dependencies_plugin")
}
maven {
url = uri("file:../../third_party/dependencies_new")
diff --git a/d8_r8/settings.gradle.kts b/d8_r8/settings.gradle.kts
index ac9216a..ad7577f 100644
--- a/d8_r8/settings.gradle.kts
+++ b/d8_r8/settings.gradle.kts
@@ -51,7 +51,7 @@
process.waitFor()
if (process.exitValue() != 0) {
throw GradleException(
- "Bootstrapping dependencies_new download failed:\n"
+ "Bootstrapping ${outputDir} download failed:\n"
+ "${String(process.getErrorStream().readAllBytes(),
java.nio.charset.StandardCharsets.UTF_8)}\n"
+ String(process.getInputStream().readAllBytes(),
@@ -68,6 +68,7 @@
val thirdParty = getRepoRoot().resolve("third_party")
downloadFromGoogleStorage(thirdParty.resolve("dependencies"))
downloadFromGoogleStorage(thirdParty.resolve("dependencies_new"))
+downloadFromGoogleStorage(thirdParty.resolve("dependencies_plugin"))
pluginManagement {
repositories {
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 af882b2..6c86022 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -987,6 +987,7 @@
throws ExecutionException {
rewriteWithLensAndApplication(
lens, application, executorService, timing, withClassHierarchy(), lens.getPrevious());
+ assert verifyMovedMethodsHaveOriginalMethodPosition();
}
private static void rewriteWithLensAndApplication(
@@ -1295,4 +1296,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..49f51d8 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 position) {
+ super(newConstructor.holder, newConstructor, position);
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..38b47fc 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();
@@ -271,25 +273,20 @@
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 +378,24 @@
}
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(newMethodReference, 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..a8e46f9 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
@@ -15,26 +15,22 @@
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) {
+ DexField classIdField) {
this.typeConstructors = typeConstructors;
this.newConstructor = newConstructor;
this.classIdField = classIdField;
- this.originalMethod = originalMethod;
}
@Override
public SourceCodeProvider getSourceCodeProvider() {
- return (ignored, callerPosition) ->
- new ConstructorEntryPoint(
- typeConstructors, newConstructor, classIdField, callerPosition, originalMethod);
+ return (ignored, position) ->
+ new ConstructorEntryPoint(typeConstructors, newConstructor, classIdField, position);
}
@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/InvokeType.java b/src/main/java/com/android/tools/r8/ir/code/InvokeType.java
index de333be..9d9fad1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeType.java
@@ -96,7 +96,14 @@
if (holderType != null
&& holderType.isInANest()
&& holderType.isInSameNest(context.getHolder())) {
- return InvokeType.DIRECT;
+ // Invoking a private super method within a nest must use invoke-direct. Invoking a
+ // non-private super method within a nest must use invoke-super.
+ MethodLookupResult lookupResult =
+ graphLens.lookupMethod(invokedMethod, context.getReference(), InvokeType.DIRECT);
+ DexEncodedMethod definition = holderType.lookupMethod(lookupResult.getReference());
+ return definition != null && definition.isPrivate()
+ ? InvokeType.DIRECT
+ : InvokeType.SUPER;
}
}
return InvokeType.SUPER;
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 d7dee5a..73e94aa 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
@@ -1057,7 +1057,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 5888f9e..32e5a1a 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
@@ -932,8 +932,9 @@
method, localUtilityClass, availableMethodSignatures, method.getReference());
return method
.getDefinition()
- .toTypeSubstitutedMethod(
+ .toTypeSubstitutedMethodAsInlining(
newMethod,
+ factory,
builder ->
transformMethodForLocalUtility(builder, method)
.setCompilationState(method.getDefinition().getCompilationState()));
@@ -950,8 +951,9 @@
DexEncodedMethod dexEncodedMethod =
method
.getDefinition()
- .toTypeSubstitutedMethod(
+ .toTypeSubstitutedMethodAsInlining(
newMethod,
+ factory,
builder ->
transformMethodForLocalUtility(builder, method)
.modifyAccessFlags(MethodAccessFlags::unsetAbstract)
@@ -1032,8 +1034,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 6c0e779..6873f86 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
@@ -1268,8 +1268,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);
@@ -1752,11 +1753,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());
@@ -1803,7 +1803,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..7a9429c 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;
@@ -17,6 +19,7 @@
import com.android.tools.r8.ir.code.IRCode;
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.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.MethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
@@ -46,12 +49,18 @@
AppView<?> appView,
Origin origin,
MutableMethodConversionOptions conversionOptions) {
- return IRBuilder.create(method, appView, getSourceCodeProvider().get(method, null), origin)
+ SyntheticPosition position =
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(method.getReference())
+ .setIsD8R8Synthesized(true)
+ .build();
+ return IRBuilder.create(method, appView, getSourceCodeProvider().get(method, position), origin)
.build(method, conversionOptions);
}
@Override
- public IRCode buildInliningIR(
+ public final IRCode buildInliningIR(
ProgramMethod context,
ProgramMethod method,
AppView<?> appView,
@@ -72,6 +81,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..c1fbd37 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;
@@ -86,15 +79,14 @@
return this;
}
- public ForwardMethodSourceCode build(ProgramMethod context, Position callerPosition) {
+ public ForwardMethodSourceCode build(ProgramMethod context, Position position) {
return new ForwardMethodSourceCode(
receiver,
method,
- originalMethod,
targetReceiver,
target,
invokeType,
- callerPosition,
+ position,
isInterface,
castResult,
extraNullParameter);
@@ -111,15 +103,14 @@
ForwardMethodSourceCode(
DexType receiver,
DexMethod method,
- DexMethod originalMethod,
DexType targetReceiver,
DexMethod target,
InvokeType invokeType,
- Position callerPosition,
+ Position position,
boolean isInterface,
boolean castResult,
boolean extraNullParameter) {
- super(receiver, method, callerPosition, originalMethod);
+ super(receiver, method, position);
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..4e3bf9c 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
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.DexSourceCode;
import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -44,16 +43,12 @@
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) {
+ protected SyntheticSourceCode(DexType receiver, DexMethod method, Position position) {
assert method != null;
this.receiver = receiver;
this.method = method;
this.proto = method.proto;
+ this.position = position;
// Initialize register values for receiver and arguments
this.receiverRegister = receiver != null ? nextRegister(ValueType.OBJECT) : -1;
@@ -64,14 +59,6 @@
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();
}
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..f96b242 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,21 +2283,11 @@
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;
}
@Override
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/examplesJava11/nesthostexample/NestHierachy.java b/src/test/examplesJava11/nesthostexample/NestHierachy.java
new file mode 100644
index 0000000..ba971d2
--- /dev/null
+++ b/src/test/examplesJava11/nesthostexample/NestHierachy.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package nesthostexample;
+
+public class NestHierachy {
+ abstract static class InnerSuper {
+ public void m1() {
+ System.out.println("m1");
+ }
+
+ private void m2() {
+ System.out.println("m2");
+ }
+
+ private void m3() {
+ System.out.println("m3");
+ }
+
+ public static void s1() {
+ System.out.println("s1");
+ }
+
+ private static void s2() {
+ System.out.println("s2");
+ }
+ }
+
+ static class InnerSub extends InnerSuper {
+ public void m1() {
+ super.m1();
+ }
+
+ public void m2() {
+ super.m2();
+ }
+
+ private void m3() {
+ super.m3();
+ }
+
+ public static void s1() {
+ InnerSuper.s1();
+ }
+
+ private static void s2() {
+ InnerSuper.s2();
+ }
+ }
+
+ public static void callOnInnerSuper(InnerSuper innerSuper) {
+ innerSuper.m1();
+ innerSuper.m2();
+ innerSuper.m3();
+ innerSuper.s1();
+ innerSuper.s2();
+ }
+
+ public static void callOnInnerSub(InnerSub innerSub) {
+ innerSub.m1();
+ innerSub.m2();
+ innerSub.m3();
+ innerSub.s1();
+ innerSub.s2();
+ }
+
+ public static void main(String[] args) {
+ callOnInnerSuper(new InnerSub());
+ callOnInnerSub(new InnerSub());
+ InnerSuper.s1();
+ InnerSuper.s2();
+ InnerSub.s1();
+ InnerSub.s2();
+ }
+}
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/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSpecialTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSpecialTest.java
new file mode 100644
index 0000000..b50b2f9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSpecialTest.java
@@ -0,0 +1,222 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.desugar.nestaccesscontrol;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.google.common.base.Predicates.alwaysTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.Predicate;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class NestAttributesInDexRewriteInvokeSpecialTest extends NestAttributesInDexTestBase {
+
+ private static final Path JDK17_JAR =
+ Paths.get(ToolHelper.TESTS_BUILD_DIR, "examplesJava11")
+ .resolve("nesthostexample" + JAR_EXTENSION);
+ private static final String MAIN = "nesthostexample.NestHierachy";
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+ }
+
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines(
+ "m1", "m2", "m3", "s1", "s2", "m1", "m2", "m3", "s1", "s2", "s1", "s2", "s1", "s2");
+
+ @Test
+ public void testRuntime() throws Exception {
+ assumeTrue(parameters.isCfRuntime() && isRuntimeWithNestSupport(parameters.asCfRuntime()));
+ testForJvm(parameters)
+ .addProgramFiles(JDK17_JAR)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ parameters.assumeDexRuntime();
+ testForD8()
+ .addProgramFiles(JDK17_JAR)
+ .setMinApi(parameters)
+ .compile()
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+
+ private void assertSingleInvokeSuper(MethodSubject method, Predicate<String> methodNameFilter) {
+ long invokeCount =
+ method
+ .streamInstructions()
+ .filter(InstructionSubject::isInvoke)
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ long invokeSuperCount =
+ method
+ .streamInstructions()
+ .filter(instruction -> instruction.asDexInstruction().isInvokeSuper())
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ assertEquals(1, invokeCount);
+ assertEquals(1, invokeSuperCount);
+ }
+
+ private void assertSingleInvokeDirect(MethodSubject method, Predicate<String> methodNameFilter) {
+ long invokeCount =
+ method
+ .streamInstructions()
+ .filter(InstructionSubject::isInvoke)
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ long invokeSuperCount =
+ method
+ .streamInstructions()
+ .filter(instruction -> instruction.asDexInstruction().isInvokeDirect())
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ assertEquals(1, invokeCount);
+ assertEquals(1, invokeSuperCount);
+ }
+
+ private void assertSingleInvokeVirtual(MethodSubject method, Predicate<String> methodNameFilter) {
+ long invokeCount =
+ method
+ .streamInstructions()
+ .filter(InstructionSubject::isInvoke)
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ long invokeVirtualCount =
+ method
+ .streamInstructions()
+ .filter(InstructionSubject::isInvokeVirtual)
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ assertEquals(1, invokeCount);
+ assertEquals(1, invokeVirtualCount);
+ }
+
+ private void assertSingleInvokeStatic(MethodSubject method, Predicate<String> methodNameFilter) {
+ long invokeCount =
+ method
+ .streamInstructions()
+ .filter(InstructionSubject::isInvoke)
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ long invokeVirtualCount =
+ method
+ .streamInstructions()
+ .filter(InstructionSubject::isInvokeStatic)
+ .filter(
+ instruction -> methodNameFilter.test(instruction.getMethod().getName().toString()))
+ .count();
+ assertEquals(1, invokeCount);
+ assertEquals(1, invokeVirtualCount);
+ }
+
+ private void assertSingleInvokeSuper(MethodSubject method) {
+ assertSingleInvokeSuper(method, alwaysTrue());
+ }
+
+ private void assertSingleInvokeDirect(MethodSubject method) {
+ assertSingleInvokeDirect(method, alwaysTrue());
+ }
+
+ private void assertSingleInvokeStatic(MethodSubject method) {
+ assertSingleInvokeStatic(method, alwaysTrue());
+ }
+
+ private void assertSingleInvokeDirect(MethodSubject method, String invokedMethodName) {
+ assertSingleInvokeDirect(method, name -> name.equals(invokedMethodName));
+ }
+
+ private void assertSingleInvokeVirtual(MethodSubject method, String invokedMethodName) {
+ assertSingleInvokeVirtual(method, name -> name.equals(invokedMethodName));
+ }
+
+ private void assertSingleInvokeStatic(MethodSubject method, String invokedMethodName) {
+ assertSingleInvokeStatic(method, name -> name.equals(invokedMethodName));
+ }
+
+ @Test
+ public void testD8DexWithNestSupport() throws Exception {
+ parameters.assumeDexRuntime();
+ assumeTrue(parameters.getApiLevel().getLevel() >= 34);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
+ testForD8()
+ .addProgramFiles(JDK17_JAR)
+ .setMinApi(AndroidApiLevel.U)
+ .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+ .compile()
+ .inspect(
+ inspector -> {
+ ClassSubject innerSub = inspector.clazz("nesthostexample.NestHierachy$InnerSub");
+ assertThat(innerSub, isPresent());
+ // invokespecial on public super.
+ assertSingleInvokeSuper(innerSub.uniqueMethodWithOriginalName("m1"));
+ // invokespecial on private super.
+ assertSingleInvokeDirect(innerSub.uniqueMethodWithOriginalName("m2"));
+ // invokespecial on private super.
+ assertSingleInvokeDirect(innerSub.uniqueMethodWithOriginalName("m3"));
+
+ assertSingleInvokeStatic(innerSub.uniqueMethodWithOriginalName("s1"));
+ assertSingleInvokeStatic(innerSub.uniqueMethodWithOriginalName("s2"));
+
+ // invoke-virtual on public nest members, invoke-direct on private nest members
+ ClassSubject outer = inspector.clazz("nesthostexample.NestHierachy");
+ assertThat(outer, isPresent());
+ MethodSubject callOnInnerSuper =
+ outer.uniqueMethodWithOriginalName("callOnInnerSuper");
+ // invokevirtual on public in nest.
+ assertSingleInvokeVirtual(callOnInnerSuper, "m1");
+ // invokevirtual on private in nest.
+ assertSingleInvokeDirect(callOnInnerSuper, "m2");
+ // invokevirtual on private in nest.
+ assertSingleInvokeDirect(callOnInnerSuper, "m3");
+
+ assertSingleInvokeStatic(callOnInnerSuper, "s1");
+ assertSingleInvokeStatic(callOnInnerSuper, "s2");
+
+ MethodSubject callOnInnerSub = outer.uniqueMethodWithOriginalName("callOnInnerSub");
+ // invokevirtual on public in nest.
+ assertSingleInvokeVirtual(callOnInnerSub, "m1");
+ // invokevirtual on public in nest.
+ assertSingleInvokeVirtual(callOnInnerSub, "m2");
+ // invokevirtual on private in nest.
+ assertSingleInvokeDirect(callOnInnerSub, "m3");
+
+ assertSingleInvokeStatic(callOnInnerSub, "s1");
+ assertSingleInvokeStatic(callOnInnerSub, "s2");
+ });
+ }
+}
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/retrace/ProxyRetraceAmbiguousTest.java b/src/test/java/com/android/tools/r8/retrace/ProxyRetraceAmbiguousTest.java
new file mode 100644
index 0000000..b406d4e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/ProxyRetraceAmbiguousTest.java
@@ -0,0 +1,181 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ProxyRetraceAmbiguousTest extends TestBase {
+
+ private static final String MAPPING =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "package.Class$$ExternalSyntheticOutline0 -> package.internal.X:",
+ "# {'id':'sourceFile','fileName':'R8$$SyntheticClass'}",
+ "# {'id':'com.android.tools.r8.synthesized'}",
+ " 1:2:long package.$HASH$0.m(long,long,long):0:1 -> a",
+ " # {'id':'com.android.tools.r8.synthesized'}",
+ "package.Class -> package.internal.Y:",
+ "# {'id':'sourceFile','fileName':'FieldDefinition.java'}",
+ " 1:10:void foo():0:0 -> a",
+ " 11:20:void bar():0:0 -> a");
+
+ private static final List<String> STACKTRACE =
+ ImmutableList.of(
+ "Error in something",
+ " at package.internal.X.a(SourceFile:1)",
+ " at package.internal.Y.a(SourceFile)");
+
+ // TODO(b/305292991): The result should be ambiguous with 'foo' and 'bar' frames.
+ private static final List<String> UNEXPECTED_UNAMBIGUOUS =
+ ImmutableList.of("Error in something", " at package.Class.foo(FieldDefinition.java)");
+
+ // TODO(b/305292991): The result should be ambiguous with 'foo' and 'bar' frames.
+ private static final List<String> UNEXPECTED_AMBIGUOUS =
+ ImmutableList.of(
+ "Error in something",
+ "alternative 0:\n at package.Class.foo(FieldDefinition.java)",
+ "alternative 1:\n at package.Class.foo(FieldDefinition.java)");
+
+ // TODO(b/305292991): The result should be ambiguous with 'foo' and 'bar' frames.
+ private static final List<String> UNEXPECTED_AMBIGUOUS_JOINED =
+ ImmutableList.of(
+ "Error in something",
+ " at package.Class.foo(FieldDefinition.java)",
+ " at package.Class.foo(FieldDefinition.java)");
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public ProxyRetraceAmbiguousTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
+ private List<String> joinResult(List<RetraceStackFrameAmbiguousResult<String>> result) {
+ List<String> lines = new ArrayList<>();
+ for (RetraceStackFrameAmbiguousResult<String> potentiallyAmbiguousFrame : result) {
+ if (potentiallyAmbiguousFrame.isAmbiguous()) {
+ for (int i = 0; i < potentiallyAmbiguousFrame.size(); i++) {
+ StringBuilder builder = new StringBuilder("alternative ").append(i).append(":\n");
+ potentiallyAmbiguousFrame.get(i).forEach(s -> builder.append(s).append('\n'));
+ // Remove the last newline to stay consistent with "list of lines".
+ String line = builder.toString();
+ lines.add(line.substring(0, line.length() - 1));
+ }
+ } else if (!potentiallyAmbiguousFrame.isEmpty()) {
+ potentiallyAmbiguousFrame.get(0).forEach(lines::add);
+ }
+ }
+ return lines;
+ }
+
+ @Test
+ public void testRetraceFullStack() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTrace(STACKTRACE, RetraceStackTraceContext.empty());
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, joinResult(result.getResult()));
+ }
+
+ @Test
+ public void testRetraceSingletonStack() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<RetraceStackFrameAmbiguousResult<String>> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTrace(Collections.singletonList(line), context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, joinResult(retraced));
+ }
+
+ @Test
+ public void testRetraceByLine() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameResultWithContext<String> result = retrace.retraceLine(line, context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED_AMBIGUOUS_JOINED, retraced);
+ }
+
+ @Test
+ public void testRetraceByFrame() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<RetraceStackFrameAmbiguousResult<String>> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameAmbiguousResultWithContext<String> result =
+ retrace.retraceFrame(line, context);
+ context = result.getContext();
+ retraced.add(result);
+ }
+ assertEquals(UNEXPECTED_AMBIGUOUS, joinResult(retraced));
+ }
+
+ @Test
+ public void testRetraceFullStackParsed() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTraceParsed(getParsedStacktrace(), RetraceStackTraceContext.empty());
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, joinResult(result.getResult()));
+ }
+
+ @Test
+ public void testRetraceSingletonStackParsed() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<RetraceStackFrameAmbiguousResult<String>> retraced = new ArrayList<>();
+ for (StackTraceElementStringProxy line : getParsedStacktrace()) {
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTraceParsed(Collections.singletonList(line), context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, joinResult(retraced));
+ }
+
+ private static List<StackTraceElementStringProxy> getParsedStacktrace() {
+ StackTraceLineParser<String, StackTraceElementStringProxy> parser = getParser();
+ return ListUtils.map(STACKTRACE, parser::parse);
+ }
+
+ private static StackTraceLineParser<String, StackTraceElementStringProxy> getParser() {
+ return StackTraceLineParser.createRegularExpressionParser(
+ RetraceOptions.defaultRegularExpression());
+ }
+
+ private static Retrace<String, StackTraceElementStringProxy> getRetraceProxy() {
+ ProguardMappingSupplier mappingSupplier =
+ ProguardMappingSupplier.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(MAPPING))
+ .build();
+ Retrace<String, StackTraceElementStringProxy> retracer =
+ new Retrace<>(getParser(), mappingSupplier, new DiagnosticsHandler() {}, false);
+ return retracer;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/ProxyRetraceOutlineTest.java b/src/test/java/com/android/tools/r8/retrace/ProxyRetraceOutlineTest.java
new file mode 100644
index 0000000..85d0ae0
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/ProxyRetraceOutlineTest.java
@@ -0,0 +1,175 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ProxyRetraceOutlineTest extends TestBase {
+
+ private static final String MAPPING =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "package.Class$$ExternalSyntheticOutline0 -> package.internal.X:",
+ "# {'id':'sourceFile','fileName':'R8$$SyntheticClass'}",
+ "# {'id':'com.android.tools.r8.synthesized'}",
+ " 1:2:long package.$HASH$0.m(long,long,long):0:1 -> a",
+ " # {'id':'com.android.tools.r8.outline'}",
+ "package.Class -> package.internal.Y:",
+ "# {'id':'sourceFile','fileName':'FieldDefinition.java'}",
+ " 1:6:void foo():21:26 -> a",
+ " 7:7:void foo():0:0 -> a",
+ " # {'id':'com.android.tools.r8.outlineCallsite',"
+ + "'positions':{'1':10,'2':11},"
+ + "'outline':'Lpackage/internal/X;a(JJJ)J'}",
+ " 8:9:void foo():38:39 -> a",
+ " 10:10:void inlineeInOutline():1337:1337 -> a",
+ " 10:10:void foo():42 -> a",
+ " 11:11:void foo():44:44 -> a");
+
+ private static final List<String> STACKTRACE =
+ ImmutableList.of(
+ "Error in something",
+ " at package.internal.X.a(SourceFile:1)",
+ " at package.internal.Y.a(SourceFile:7)");
+
+ private static final List<String> EXPECTED =
+ ImmutableList.of(
+ "Error in something",
+ " at package.Class.inlineeInOutline(FieldDefinition.java:1337)",
+ " at package.Class.foo(FieldDefinition.java:42)");
+
+ // TODO(b/305292991): These should all report EXPECTED.
+ private static final List<String> UNEXPECTED =
+ ImmutableList.of("Error in something", " at package.Class.foo(FieldDefinition.java)");
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public ProxyRetraceOutlineTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
+ private List<String> joinResult(List<RetraceStackFrameAmbiguousResult<String>> result) {
+ List<String> lines = new ArrayList<>();
+ for (RetraceStackFrameAmbiguousResult<String> potentiallyAmbiguousFrame : result) {
+ assertFalse(potentiallyAmbiguousFrame.isAmbiguous());
+ potentiallyAmbiguousFrame.forEach(
+ frameResult -> {
+ frameResult.forEach(lines::add);
+ });
+ }
+ return lines;
+ }
+
+ @Test
+ public void testRetraceFullStack() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTrace(STACKTRACE, RetraceStackTraceContext.empty());
+ assertEquals(EXPECTED, joinResult(result.getResult()));
+ }
+
+ @Test
+ public void testRetraceSingletonStack() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<RetraceStackFrameAmbiguousResult<String>> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTrace(Collections.singletonList(line), context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(EXPECTED, joinResult(retraced));
+ }
+
+ @Test
+ public void testRetraceByLine() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameResultWithContext<String> result = retrace.retraceLine(line, context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED, retraced);
+ }
+
+ @Test
+ public void testRetraceByFrame() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<RetraceStackFrameAmbiguousResult<String>> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameAmbiguousResultWithContext<String> result =
+ retrace.retraceFrame(line, context);
+ context = result.getContext();
+ retraced.add(result);
+ }
+ assertEquals(UNEXPECTED, joinResult(retraced));
+ }
+
+ @Test
+ public void testRetraceFullStackParsed() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTraceParsed(getParsedStacktrace(), RetraceStackTraceContext.empty());
+ assertEquals(EXPECTED, joinResult(result.getResult()));
+ }
+
+ @Test
+ public void testRetraceSingletonStackParsed() {
+ Retrace<String, StackTraceElementStringProxy> retrace = getRetraceProxy();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<RetraceStackFrameAmbiguousResult<String>> retraced = new ArrayList<>();
+ for (StackTraceElementStringProxy line : getParsedStacktrace()) {
+ RetraceStackTraceResult<String> result =
+ retrace.retraceStackTraceParsed(Collections.singletonList(line), context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(EXPECTED, joinResult(retraced));
+ }
+
+ private static List<StackTraceElementStringProxy> getParsedStacktrace() {
+ StackTraceLineParser<String, StackTraceElementStringProxy> parser = getParser();
+ return ListUtils.map(STACKTRACE, parser::parse);
+ }
+
+ private static StackTraceLineParser<String, StackTraceElementStringProxy> getParser() {
+ return StackTraceLineParser.createRegularExpressionParser(
+ RetraceOptions.defaultRegularExpression());
+ }
+
+ private static Retrace<String, StackTraceElementStringProxy> getRetraceProxy() {
+ ProguardMappingSupplier mappingSupplier =
+ ProguardMappingSupplier.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(MAPPING))
+ .build();
+ Retrace<String, StackTraceElementStringProxy> retracer =
+ new Retrace<>(getParser(), mappingSupplier, new DiagnosticsHandler() {}, false);
+ return retracer;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/StringRetraceAmbiguousTest.java b/src/test/java/com/android/tools/r8/retrace/StringRetraceAmbiguousTest.java
new file mode 100644
index 0000000..a092b7d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/StringRetraceAmbiguousTest.java
@@ -0,0 +1,142 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class StringRetraceAmbiguousTest extends TestBase {
+
+ private static final String MAPPING =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "package.Class$$ExternalSyntheticOutline0 -> package.internal.X:",
+ "# {'id':'sourceFile','fileName':'R8$$SyntheticClass'}",
+ "# {'id':'com.android.tools.r8.synthesized'}",
+ " 1:2:long package.$HASH$0.m(long,long,long):0:1 -> a",
+ " # {'id':'com.android.tools.r8.synthesized'}",
+ "package.Class -> package.internal.Y:",
+ "# {'id':'sourceFile','fileName':'FieldDefinition.java'}",
+ " 1:10:void foo():0:0 -> a",
+ " 11:20:void bar():0:0 -> a");
+
+ private static final List<String> STACKTRACE =
+ ImmutableList.of(
+ "Error in something",
+ " at package.internal.X.a(SourceFile:1)",
+ " at package.internal.Y.a(SourceFile)");
+
+ // TODO(b/305292991): The result should be ambiguous with 'foo' and 'bar' frames.
+ private static final List<String> UNEXPECTED_UNAMBIGUOUS =
+ ImmutableList.of("Error in something", " at package.Class.foo(FieldDefinition.java)");
+
+ // TODO(b/305292991): The result should be ambiguous with 'foo' and 'bar' frames.
+ private static final List<String> UNEXPECTED_AMBIGUOUS =
+ ImmutableList.of(
+ "Error in something",
+ "alternative 0:\n at package.Class.foo(FieldDefinition.java)",
+ "alternative 1:\n at package.Class.foo(FieldDefinition.java)");
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public StringRetraceAmbiguousTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
+ @Test
+ public void testStringRetraceAllFrames() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackFrameResultWithContext<String> result =
+ stringRetrace.retrace(STACKTRACE, RetraceStackTraceContext.empty());
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, result.getResult());
+ }
+
+ @Test
+ public void testStringRetraceSingletonStack() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameResultWithContext<String> result =
+ stringRetrace.retrace(Collections.singletonList(line), context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, retraced);
+ }
+
+ @Test
+ public void testStringRetraceByFrame() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameResultWithContext<String> result = stringRetrace.retrace(line, context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, retraced);
+ }
+
+ @Test
+ public void testStringRetraceByAmbiguousFrame() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameAmbiguousResultWithContext<String> result =
+ stringRetrace.retraceFrame(line, context);
+ context = result.getContext();
+ if (result.isAmbiguous()) {
+ for (int i = 0; i < result.size(); i++) {
+ StringBuilder builder = new StringBuilder("alternative ").append(i).append(":\n");
+ result.get(i).forEach(s -> builder.append(s).append('\n'));
+ // Remove the last newline to stay consistent with "list of lines".
+ String str = builder.toString();
+ retraced.add(str.substring(0, str.length() - 1));
+ }
+ } else if (!result.isEmpty()) {
+ result.get(0).forEach(retraced::add);
+ }
+ }
+ assertEquals(UNEXPECTED_AMBIGUOUS, retraced);
+ }
+
+ @Test
+ public void testStringRetraceSupplier() {
+ StringRetrace stringRetrace = getStringRetrace();
+ Iterator<String> iterator = STACKTRACE.iterator();
+ List<String> retraced = new ArrayList<>();
+ stringRetrace.retraceSupplier(() -> iterator.hasNext() ? iterator.next() : null, retraced::add);
+ assertEquals(UNEXPECTED_UNAMBIGUOUS, retraced);
+ }
+
+ private static StringRetrace getStringRetrace() {
+ ProguardMappingSupplier mappingSupplier =
+ ProguardMappingSupplier.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(MAPPING))
+ .build();
+
+ StringRetrace stringRetrace =
+ StringRetrace.create(RetraceOptions.builder().setMappingSupplier(mappingSupplier).build());
+ return stringRetrace;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/StringRetraceOutlineTest.java b/src/test/java/com/android/tools/r8/retrace/StringRetraceOutlineTest.java
new file mode 100644
index 0000000..475a131
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/StringRetraceOutlineTest.java
@@ -0,0 +1,143 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class StringRetraceOutlineTest extends TestBase {
+
+ private static final String MAPPING =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "package.Class$$ExternalSyntheticOutline0 -> package.internal.X:",
+ "# {'id':'sourceFile','fileName':'R8$$SyntheticClass'}",
+ "# {'id':'com.android.tools.r8.synthesized'}",
+ " 1:2:long package.$HASH$0.m(long,long,long):0:1 -> a",
+ " # {'id':'com.android.tools.r8.outline'}",
+ "package.Class -> package.internal.Y:",
+ "# {'id':'sourceFile','fileName':'FieldDefinition.java'}",
+ " 1:6:void foo():21:26 -> a",
+ " 7:7:void foo():0:0 -> a",
+ " # {'id':'com.android.tools.r8.outlineCallsite',"
+ + "'positions':{'1':10,'2':11},"
+ + "'outline':'Lpackage/internal/X;a(JJJ)J'}",
+ " 8:9:void foo():38:39 -> a",
+ " 10:10:void inlineeInOutline():1337:1337 -> a",
+ " 10:10:void foo():42 -> a",
+ " 11:11:void foo():44:44 -> a");
+
+ private static final List<String> STACKTRACE =
+ ImmutableList.of(
+ "Error in something",
+ " at package.internal.X.a(SourceFile:1)",
+ " at package.internal.Y.a(SourceFile:7)");
+
+ private static final List<String> EXPECTED =
+ ImmutableList.of(
+ "Error in something",
+ " at package.Class.inlineeInOutline(FieldDefinition.java:1337)",
+ " at package.Class.foo(FieldDefinition.java:42)");
+
+ // TODO(b/305292991): These should all report EXPECTED.
+ private static final List<String> UNEXPECTED =
+ ImmutableList.of("Error in something", " at package.Class.foo(FieldDefinition.java)");
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public StringRetraceOutlineTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
+ @Test
+ public void testStringRetraceAllFrames() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackFrameResultWithContext<String> result =
+ stringRetrace.retrace(STACKTRACE, RetraceStackTraceContext.empty());
+ assertEquals(EXPECTED, result.getResult());
+ }
+
+ @Test
+ public void testStringRetraceSingletonStack() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameResultWithContext<String> result =
+ stringRetrace.retrace(Collections.singletonList(line), context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(EXPECTED, retraced);
+ }
+
+ @Test
+ public void testStringRetraceByFrame() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameResultWithContext<String> result = stringRetrace.retrace(line, context);
+ context = result.getContext();
+ result.forEach(retraced::add);
+ }
+ assertEquals(UNEXPECTED, retraced);
+ }
+
+ @Test
+ public void testStringRetraceByAmbiguousFrame() {
+ StringRetrace stringRetrace = getStringRetrace();
+ RetraceStackTraceContext context = RetraceStackTraceContext.empty();
+ List<String> retraced = new ArrayList<>();
+ for (String line : STACKTRACE) {
+ RetraceStackFrameAmbiguousResultWithContext<String> result =
+ stringRetrace.retraceFrame(line, context);
+ context = result.getContext();
+ assertFalse(result.isAmbiguous());
+ if (!result.isEmpty()) {
+ assertEquals(1, result.size());
+ result.get(0).forEach(retraced::add);
+ }
+ }
+ assertEquals(UNEXPECTED, retraced);
+ }
+
+ @Test
+ public void testStringRetraceSupplier() {
+ StringRetrace stringRetrace = getStringRetrace();
+ Iterator<String> iterator = STACKTRACE.iterator();
+ List<String> retraced = new ArrayList<>();
+ stringRetrace.retraceSupplier(() -> iterator.hasNext() ? iterator.next() : null, retraced::add);
+ assertEquals(UNEXPECTED, retraced);
+ }
+
+ private static StringRetrace getStringRetrace() {
+ ProguardMappingSupplier mappingSupplier =
+ ProguardMappingSupplier.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(MAPPING))
+ .build();
+
+ StringRetrace stringRetrace =
+ StringRetrace.create(RetraceOptions.builder().setMappingSupplier(mappingSupplier).build());
+ return stringRetrace;
+ }
+}
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();
+ }
}
diff --git a/third_party/dependencies_plugin.tar.gz.sha1 b/third_party/dependencies_plugin.tar.gz.sha1
new file mode 100644
index 0000000..08fb793
--- /dev/null
+++ b/third_party/dependencies_plugin.tar.gz.sha1
@@ -0,0 +1 @@
+77f5f4042c4340df908bb39cdb40a67009195cac
\ No newline at end of file
diff --git a/tools/archive.py b/tools/archive.py
index 84c0da3..1632231 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -222,6 +222,12 @@
default_pom_file = os.path.join(temp, 'r8.pom')
create_maven_release.write_default_r8_pom_file(default_pom_file,
version)
+ gradle.RunGradle([
+ ':main:spdxSbom',
+ '-PspdxVersion=' + version,
+ '-PspdxRevision=' + GetGitHash()
+ ])
+
for_archiving = [
utils.R8_JAR, utils.R8LIB_JAR, utils.R8LIB_JAR + '.map',
utils.R8LIB_JAR + '_map.zip', utils.R8_FULL_EXCLUDE_DEPS_JAR,
@@ -237,7 +243,9 @@
utils.R8RETRACE_JAR + '_map.zip', utils.R8RETRACE_EXCLUDE_DEPS_JAR,
utils.R8RETRACE_EXCLUDE_DEPS_JAR + '.map',
utils.R8RETRACE_EXCLUDE_DEPS_JAR + '_map.zip',
- utils.KEEPANNO_ANNOTATIONS_JAR, utils.GENERATED_LICENSE
+ utils.KEEPANNO_ANNOTATIONS_JAR,
+ utils.GENERATED_LICENSE,
+ 'd8_r8/main/build/spdx/r8.spdx.json'
]
for file in for_archiving:
file_name = os.path.basename(file)
diff --git a/tools/create_local_maven_with_dependencies.py b/tools/create_local_maven_with_dependencies.py
index 4ae9d25..e5d8885 100755
--- a/tools/create_local_maven_with_dependencies.py
+++ b/tools/create_local_maven_with_dependencies.py
@@ -11,13 +11,13 @@
import utils
-# The local_maven_repository_generator orderes the repositories by name, so
+# The local_maven_repository_generator orders the repositories by name, so
# prefix with X- to control the order, as many dependencies are present
-# in several repositories.
+# in several repositories. Save A- for additional local repository.
REPOSITORIES = [
- 'A-Google=https://maven.google.com/',
- 'B-Maven Central=https://repo1.maven.org/maven2/',
- "C-Gradle Plugins=https://plugins.gradle.org/m2/",
+ 'B-Google=https://maven.google.com/',
+ 'C-Maven Central=https://repo1.maven.org/maven2/',
+ "D-Gradle Plugins=https://plugins.gradle.org/m2/",
]
ANDRDID_SUPPORT_VERSION = '25.4.0'
@@ -97,6 +97,11 @@
version=PROTOBUF_VERSION),
]
+PLUGIN_DEPENDENCIES = [
+ 'org.spdx.sbom:org.spdx.sbom.gradle.plugin:0.2.0-r8-patch01',
+ # See https://github.com/FasterXML/jackson-core/issues/999.
+ 'ch.randelshofer:fastdoubleparser:0.8.0',
+]
def dependencies_tar(dependencies_path):
return os.path.join(os.path.dirname(dependencies_path),
@@ -143,32 +148,89 @@
required=True,
help='Path to a studio-main checkout (to get the tool '
'//tools/base/bazel:local_maven_repository_generator_cli)')
+ result.add_argument(
+ '--plugin-deps',
+ '--plugin_deps',
+ default=False,
+ action='store_true',
+ help='Build repository Gradle plugin dependncies')
+ result.add_argument(
+ '--include-maven-local',
+ '--include_maven_local',
+ metavar=('<path>'),
+ default=False,
+ help='Path to maven local repository to include as dependency source')
+ result.add_argument(
+ '--no-upload',
+ '--no_upload',
+ default=False,
+ action='store_true',
+ help="Don't upload to Google CLoud Storage")
return result.parse_args()
+def set_utime(path):
+ os.utime(path, (0, 0))
+ for root, dirs, files in os.walk(path):
+ for f in files:
+ os.utime(os.path.join(root, f), (0, 0))
+ for d in dirs:
+ os.utime(os.path.join(root, d), (0, 0))
+
def main():
args = parse_options()
- dependencies_path = os.path.join(utils.THIRD_PARTY, 'dependencies')
- print("Downloading to " + dependencies_path)
- remove_local_maven_repository(dependencies_path)
- create_local_maven_repository(args, dependencies_path, REPOSITORIES,
- BUILD_DEPENDENCIES + TEST_DEPENDENCIES)
+ repositories = REPOSITORIES
+ if args.include_maven_local:
+ # Add the local repository as the first for it to take precedence.
+ # Use A- prefix as current local_maven_repository_generator orderes by name.
+ repositories = ['A-Local=file://%s' % args.include_maven_local] + REPOSITORIES
- dependencies_new_path = os.path.join(utils.THIRD_PARTY, 'dependencies_new')
- print("Downloading to " + dependencies_new_path)
- remove_local_maven_repository(dependencies_new_path)
- create_local_maven_repository(args, dependencies_new_path, REPOSITORIES,
- NEW_DEPENDENCIES)
+ dependencies = []
- print("Uploading to Google Cloud Storage:")
- with utils.ChangedWorkingDirectory(utils.THIRD_PARTY):
- for dependency in ['dependencies', 'dependencies_new']:
- cmd = [
- 'upload_to_google_storage.py', '-a', '--bucket', 'r8-deps',
- dependency
- ]
- subprocess.check_call(cmd)
+ if args.plugin_deps:
+ dependencies_plugin_path = os.path.join(utils.THIRD_PARTY, 'dependencies_plugin')
+ remove_local_maven_repository(dependencies_plugin_path)
+ print("Downloading to " + dependencies_plugin_path)
+ create_local_maven_repository(
+ args, dependencies_plugin_path, repositories, PLUGIN_DEPENDENCIES)
+ set_utime(dependencies_plugin_path)
+ dependencies.append('dependencies_plugin')
+ else:
+ dependencies_path = os.path.join(utils.THIRD_PARTY, 'dependencies')
+ remove_local_maven_repository(dependencies_path)
+ print("Downloading to " + dependencies_path)
+ create_local_maven_repository(
+ args, dependencies_path, repositories, BUILD_DEPENDENCIES + TEST_DEPENDENCIES)
+ set_utime(dependencies_path)
+ dependencies.append('dependencies')
+ dependencies_new_path = os.path.join(utils.THIRD_PARTY, 'dependencies_new')
+ remove_local_maven_repository(dependencies_new_path)
+ print("Downloading to " + dependencies_new_path)
+ create_local_maven_repository(
+ args, dependencies_new_path, repositories, NEW_DEPENDENCIES)
+ set_utime(dependencies_new_path)
+ dependencies.append('dependencies_new')
+
+ upload_cmds = []
+ for dependency in dependencies:
+ upload_cmds.append([
+ 'upload_to_google_storage.py',
+ '-a',
+ '--bucket',
+ 'r8-deps',
+ dependency])
+
+ if not args.no_upload:
+ print("Uploading to Google Cloud Storage:")
+ with utils.ChangedWorkingDirectory(utils.THIRD_PARTY):
+ for cmd in upload_cmds:
+ subprocess.check_call(cmd)
+ else:
+ print("Not uploading to Google Cloud Storage. "
+ + "Run the following commands in %s to do so manually" % utils.THIRD_PARTY)
+ for cmd in upload_cmds:
+ print(" ".join(cmd))
if __name__ == '__main__':