Merge commit 'cfe1b2aae0b66991cdf07cdd059d350b60799ed8' into dev-release
diff --git a/.gitignore b/.gitignore
index 6d67701..13e30c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@
android-data*/
build/
buildSrc/out/
+src/*/out
gradle-app.setting
gradle/*
gradlew
@@ -25,6 +26,7 @@
r8.ipr
r8.iws
src/test/jack/ub-jack
+test_modules/tests_java_8/libs/
tests/2016-12-19/art
tests/2016-12-19/art.tar.gz
tests/2017-10-04/art
@@ -99,6 +101,8 @@
third_party/gradle-plugin.tar.gz
third_party/gradle/gradle
third_party/gradle/gradle.tar.gz
+third_party/gradle/gradle-8.0
+third_party/gradle/gradle-8.0.tar.gz
third_party/internal/*
third_party/iosched_2019
third_party/iosched_2019.tar.gz
@@ -282,6 +286,8 @@
tools/*/host/art-12.0.0-beta4.tar.gz
tools/*/host/art-13.0.0
tools/*/host/art-13.0.0.tar.gz
+tools/*/host/art-14.0.0-dp1
+tools/*/host/art-14.0.0-dp1.tar.gz
tools/*/host/art-master
tools/*/host/art-master.tar.gz
tools/*/art.tar.gz
diff --git a/build.gradle b/build.gradle
index 759507d..11cc609 100644
--- a/build.gradle
+++ b/build.gradle
@@ -393,6 +393,7 @@
"linux/art-10.0.0",
"linux/host/art-12.0.0-beta4",
"linux/host/art-13.0.0",
+ "linux/host/art-14.0.0-dp1",
"linux/host/art-master",
"linux/dalvik",
"linux/dalvik-4.0.4",
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 3f4e21f..88e29ab 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -7,18 +7,19 @@
repositories {
mavenCentral()
}
+
ext {
asmVersion = '9.4'
}
dependencies {
- compile group: 'com.google.guava', name: 'guava', version: '19.0'
- compile group: 'org.smali', name: 'smali', version: '2.2b4'
- compile group: 'org.ow2.asm', name: 'asm', version: asmVersion
- compile group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion
- compile group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion
- compile group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion
- compile group: 'org.ow2.asm', name: 'asm-util', version: asmVersion
+ implementation group: 'com.google.guava', name: 'guava', version: '30.1.1-jre'
+ implementation group: 'org.smali', name: 'smali', version: '2.2b4'
+ implementation group: 'org.ow2.asm', name: 'asm', version: asmVersion
+ implementation group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion
+ implementation group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion
+ implementation group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion
+ implementation group: 'org.ow2.asm', name: 'asm-util', version: asmVersion
}
sourceCompatibility = JavaVersion.VERSION_1_8
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java
index bae3c1c..1a09676 100644
--- a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java
@@ -9,10 +9,12 @@
import java.io.UncheckedIOException;
import javax.inject.Inject;
import org.gradle.api.DefaultTask;
+import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
-import org.gradle.workers.IsolationMode;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
import org.gradle.workers.WorkerExecutor;
public class CustomConversionAsmRewriterTask extends DefaultTask {
@@ -47,29 +49,31 @@
@TaskAction
void exec() {
- workerExecutor.submit(
- Run.class,
- config -> {
- config.setIsolationMode(IsolationMode.NONE);
- config.params(rawJar, outputDirectory);
- });
+ workerExecutor
+ .noIsolation()
+ .submit(
+ Run.class,
+ parameters -> {
+ parameters.getRawJar().set(rawJar);
+ parameters.getOutputDirectory().set(outputDirectory);
+ });
}
- public static class Run implements Runnable {
+ public interface RunParameters extends WorkParameters {
+ RegularFileProperty getRawJar();
- private final File rawJar;
- private final File outputDirectory;
+ RegularFileProperty getOutputDirectory();
+ }
- @Inject
- public Run(File rawJar, File outputDirectory) {
- this.rawJar = rawJar;
- this.outputDirectory = outputDirectory;
- }
+ public abstract static class Run implements WorkAction<RunParameters> {
@Override
- public void run() {
+ public void execute() {
try {
- CustomConversionAsmRewriter.generateJars(rawJar.toPath(), outputDirectory.toPath());
+ RunParameters parameters = getParameters();
+ CustomConversionAsmRewriter.generateJars(
+ parameters.getRawJar().getAsFile().get().toPath(),
+ parameters.getOutputDirectory().getAsFile().get().toPath());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
diff --git a/buildSrc/src/main/java/dx/DexMergerTask.java b/buildSrc/src/main/java/dx/DexMergerTask.java
index 5dea52b..409337c 100644
--- a/buildSrc/src/main/java/dx/DexMergerTask.java
+++ b/buildSrc/src/main/java/dx/DexMergerTask.java
@@ -3,20 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
package dx;
-import com.google.common.base.Optional;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
import javax.inject.Inject;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.FileCollection;
-import org.gradle.api.tasks.InputFile;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
-import org.gradle.workers.IsolationMode;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
import org.gradle.workers.WorkerExecutor;
import utils.Utils;
@@ -26,7 +26,6 @@
private FileCollection source;
private File destination;
- private Optional<File> dexMergerExecutable = Optional.absent(); // Worker API cannot handle null.
@Inject
public DexMergerTask(WorkerExecutor workerExecutor) {
@@ -51,57 +50,39 @@
this.destination = destination;
}
- @InputFile
- @org.gradle.api.tasks.Optional
- public File getDexMergerExecutable() {
- return dexMergerExecutable.orNull();
- }
-
- public void setDexMergerExecutable(File dexMergerExecutable) {
- this.dexMergerExecutable = Optional.fromNullable(dexMergerExecutable);
- }
-
@TaskAction
void exec() {
- workerExecutor.submit(
- RunDexMerger.class,
- config -> {
- File executable =
- dexMergerExecutable.isPresent()
- ? dexMergerExecutable.get()
- : config
- .getForkOptions()
- .getWorkingDir()
- .toPath()
- .resolve(Utils.dexMergerExecutable())
- .toFile();
- config.setIsolationMode(IsolationMode.NONE);
- config.params(source.getFiles(), destination, executable);
- });
+ workerExecutor
+ .noIsolation()
+ .submit(
+ RunDexMerger.class,
+ parameters -> {
+ parameters.getSources().set(source.getFiles());
+ parameters.getDestination().set(destination);
+ });
}
- public static class RunDexMerger implements Runnable {
- private final Set<File> sources;
- private final File destination;
- private final File dexMergerExecutable;
+ public interface RunDexMergerParameters extends WorkParameters {
- @Inject
- public RunDexMerger(Set<File> sources, File destination, File dexMergerExecutable) {
- this.sources = sources;
- this.destination = destination;
- this.dexMergerExecutable = dexMergerExecutable;
- }
+ SetProperty<File> getSources();
+
+ RegularFileProperty getDestination();
+
+ RegularFileProperty getDexMergerExecutable();
+ }
+
+ public abstract static class RunDexMerger implements WorkAction<RunDexMergerParameters> {
@Override
- public void run() {
+ public void execute() {
try {
+ RunDexMergerParameters parameters = getParameters();
List<String> command = new ArrayList<>();
- command.add(dexMergerExecutable.getCanonicalPath());
- command.add(destination.getCanonicalPath());
- for (File source : sources) {
+ command.add(Utils.dexMergerExecutable().toString());
+ command.add(parameters.getDestination().getAsFile().get().getCanonicalPath());
+ for (File source : parameters.getSources().get()) {
command.add(source.getCanonicalPath());
}
-
Process dexMerger = new ProcessBuilder(command).inheritIO().start();
int exitCode = dexMerger.waitFor();
if (exitCode != 0) {
diff --git a/buildSrc/src/main/java/dx/DxTask.java b/buildSrc/src/main/java/dx/DxTask.java
index e05e8fb..a66733a 100644
--- a/buildSrc/src/main/java/dx/DxTask.java
+++ b/buildSrc/src/main/java/dx/DxTask.java
@@ -3,22 +3,23 @@
// BSD-style license that can be found in the LICENSE file.
package dx;
-import com.google.common.base.Optional;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
import javax.inject.Inject;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.Property;
+import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input;
-import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
-import org.gradle.workers.IsolationMode;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
import org.gradle.workers.WorkerExecutor;
import utils.Utils;
@@ -28,7 +29,6 @@
private FileCollection source;
private File destination;
- private Optional<File> dxExecutable = Optional.absent(); // Worker API cannot handle null.
private boolean debug;
@Inject
@@ -54,16 +54,6 @@
this.destination = destination;
}
- @InputFile
- @org.gradle.api.tasks.Optional
- public File getDxExecutable() {
- return dxExecutable.orNull();
- }
-
- public void setDxExecutable(File dxExecutable) {
- this.dxExecutable = Optional.fromNullable(dxExecutable);
- }
-
@Input
public boolean isDebug() {
return debug;
@@ -75,49 +65,41 @@
@TaskAction
void exec() {
- workerExecutor.submit(
- RunDx.class,
- config -> {
- File executable =
- dxExecutable.isPresent()
- ? dxExecutable.get()
- : config
- .getForkOptions()
- .getWorkingDir()
- .toPath()
- .resolve(Utils.dxExecutable())
- .toFile();
- config.setIsolationMode(IsolationMode.NONE);
- config.params(source.getFiles(), destination, executable, debug);
- });
+ workerExecutor
+ .noIsolation()
+ .submit(
+ RunDx.class,
+ parameters -> {
+ parameters.getSources().set(source.getFiles());
+ parameters.getDestination().set(destination);
+ parameters.getDebug().set(debug);
+ });
}
- public static class RunDx implements Runnable {
- private final Set<File> sources;
- private final File destination;
- private final File dxExecutable;
- private final boolean debug;
+ public interface RunDxParameters extends WorkParameters {
- @Inject
- public RunDx(Set<File> sources, File destination, File dxExecutable, boolean debug) {
- this.sources = sources;
- this.destination = destination;
- this.dxExecutable = dxExecutable;
- this.debug = debug;
- }
+ SetProperty<File> getSources();
+
+ RegularFileProperty getDestination();
+
+ Property<Boolean> getDebug();
+ }
+
+ public abstract static class RunDx implements WorkAction<RunDxParameters> {
@Override
- public void run() {
+ public void execute() {
+ RunDxParameters parameters = getParameters();
try {
List<String> command = new ArrayList<>();
- command.add(dxExecutable.getCanonicalPath());
+ command.add(Utils.dxExecutable().toString());
command.add("--dex");
command.add("--output");
- command.add(destination.getCanonicalPath());
- if (debug) {
+ command.add(parameters.getDestination().getAsFile().get().getCanonicalPath());
+ if (parameters.getDebug().get()) {
command.add("--debug");
}
- for (File source : sources) {
+ for (File source : parameters.getSources().get()) {
command.add(source.getCanonicalPath());
}
diff --git a/buildSrc/src/main/java/smali/SmaliTask.java b/buildSrc/src/main/java/smali/SmaliTask.java
index 845592e..dd4e10c 100644
--- a/buildSrc/src/main/java/smali/SmaliTask.java
+++ b/buildSrc/src/main/java/smali/SmaliTask.java
@@ -9,14 +9,16 @@
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.List;
-import java.util.Set;
import javax.inject.Inject;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.FileTree;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
-import org.gradle.workers.IsolationMode;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
import org.gradle.workers.WorkerExecutor;
import org.jf.smali.Smali;
import org.jf.smali.SmaliOptions;
@@ -53,28 +55,33 @@
@TaskAction
void exec() {
- workerExecutor.submit(RunSmali.class, config -> {
- config.setIsolationMode(IsolationMode.NONE);
- config.params(source.getFiles(), destination);
- });
+ workerExecutor
+ .noIsolation()
+ .submit(
+ RunSmali.class,
+ parameters -> {
+ parameters.getSources().set(source.getFiles());
+ parameters.getDestination().set(destination);
+ });
}
- public static class RunSmali implements Runnable {
- private final Set<File> sources;
- private final File destination;
+ public interface RunSmaliParameters extends WorkParameters {
- @Inject
- public RunSmali(Set<File> sources, File destination) {
- this.sources = sources;
- this.destination = destination;
- }
+ SetProperty<File> getSources();
+
+ RegularFileProperty getDestination();
+ }
+
+ public abstract static class RunSmali implements WorkAction<RunSmaliParameters> {
@Override
- public void run() {
+ public void execute() {
try {
- List<String> fileNames = sources.stream().map(File::toString).collect(toList());
+ RunSmaliParameters parameters = getParameters();
+ List<String> fileNames =
+ parameters.getSources().get().stream().map(File::toString).collect(toList());
SmaliOptions options = new SmaliOptions();
- options.outputDexFile = destination.getCanonicalPath();
+ options.outputDexFile = parameters.getDestination().getAsFile().get().getCanonicalPath();
Smali.assemble(options, fileNames);
} catch (IOException e) {
throw new UncheckedIOException(e);
diff --git a/buildSrc/src/main/java/tasks/DownloadDependency.java b/buildSrc/src/main/java/tasks/DownloadDependency.java
index 59596a8..6d7a75c 100644
--- a/buildSrc/src/main/java/tasks/DownloadDependency.java
+++ b/buildSrc/src/main/java/tasks/DownloadDependency.java
@@ -15,11 +15,14 @@
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.gradle.api.DefaultTask;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.Property;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.internal.os.OperatingSystem;
-import org.gradle.workers.IsolationMode;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
import org.gradle.workers.WorkerExecutor;
public class DownloadDependency extends DefaultTask {
@@ -88,29 +91,34 @@
if (outputDir.exists() && outputDir.isDirectory()) {
outputDir.delete();
}
- workerExecutor.submit(RunDownload.class, config -> {
- config.setIsolationMode(IsolationMode.NONE);
- config.params(type, sha1File);
- });
+ workerExecutor
+ .noIsolation()
+ .submit(
+ RunDownload.class,
+ parameters -> {
+ parameters.getType().set(type);
+ parameters.getSha1File().set(sha1File);
+ });
}
- public static class RunDownload implements Runnable {
- private final Type type;
- private final File sha1File;
+ public interface RunDownloadParameters extends WorkParameters {
+ Property<Type> getType();
- @Inject
- public RunDownload(Type type, File sha1File) {
- this.type = type;
- this.sha1File = sha1File;
- }
+ RegularFileProperty getSha1File();
+ }
+
+ public abstract static class RunDownload implements WorkAction<RunDownloadParameters> {
@Override
- public void run() {
+ public void execute() {
try {
+ RunDownloadParameters parameters = getParameters();
+ Type type = parameters.getType().get();
+ File sha1File = parameters.getSha1File().getAsFile().get();
if (type == Type.GOOGLE_STORAGE) {
- downloadFromGoogleStorage();
+ downloadFromGoogleStorage(sha1File);
} else if (type == Type.X20) {
- downloadFromX20();
+ downloadFromX20(sha1File);
} else {
throw new RuntimeException("Unexpected or missing dependency type: " + type);
}
@@ -119,7 +127,7 @@
}
}
- private void downloadFromGoogleStorage() throws IOException, InterruptedException {
+ private void downloadFromGoogleStorage(File sha1File) throws IOException, InterruptedException {
List<String> args = Arrays.asList("-n", "-b", "r8-deps", "-s", "-u", sha1File.toString());
if (OperatingSystem.current().isWindows()) {
List<String> command = new ArrayList<>();
@@ -133,7 +141,7 @@
}
}
- private void downloadFromX20() throws IOException, InterruptedException {
+ private void downloadFromX20(File sha1File) throws IOException, InterruptedException {
if (OperatingSystem.current().isWindows()) {
throw new RuntimeException("Downloading from x20 unsupported on windows");
}
diff --git a/commonBuildSrc/build.gradle.kts b/commonBuildSrc/build.gradle.kts
new file mode 100644
index 0000000..ba393c7
--- /dev/null
+++ b/commonBuildSrc/build.gradle.kts
@@ -0,0 +1,15 @@
+// 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.
+
+plugins {
+ `kotlin-dsl`
+ `java-gradle-plugin`
+}
+
+gradlePlugin {
+ plugins.register("dependencies-plugin") {
+ id = "dependencies-plugin"
+ implementationClass = "DependenciesPlugin"
+ }
+}
diff --git a/commonBuildSrc/settings.gradle.kts b/commonBuildSrc/settings.gradle.kts
new file mode 100644
index 0000000..b7d4523
--- /dev/null
+++ b/commonBuildSrc/settings.gradle.kts
@@ -0,0 +1,18 @@
+// 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.
+
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "common-build-src"
diff --git a/commonBuildSrc/src/main/kotlin/Dependencies.kt b/commonBuildSrc/src/main/kotlin/Dependencies.kt
new file mode 100644
index 0000000..b93dbcf
--- /dev/null
+++ b/commonBuildSrc/src/main/kotlin/Dependencies.kt
@@ -0,0 +1,63 @@
+// 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.
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.JavaVersion
+import java.io.File
+
+class DependenciesPlugin: Plugin<Project> {
+ override fun apply(target: Project) {
+ // Intentionally empty
+ }
+}
+
+fun Project.getRoot() : File {
+ var parent = this.projectDir
+ while (!parent.getName().equals("d8_r8")) {
+ parent = parent.getParentFile()
+ }
+ return parent.getParentFile()
+}
+
+fun File.resolveAll(vararg xs: String) : File {
+ var that = this;
+ for (x in xs) {
+ that = that.resolve(x)
+ }
+ return that
+}
+
+object JvmCompatibility {
+ val sourceCompatibility = JavaVersion.VERSION_11
+ val targetCompatibility = JavaVersion.VERSION_11
+}
+
+object Versions {
+ const val asmVersion = "9.4"
+ const val fastUtilVersion = "7.2.0"
+ const val gsonVersion = "2.7"
+ const val guavaVersion = "30.1.1-jre"
+ const val joptSimpleVersion = "4.6"
+ const val junitVersion = "4.13-beta-2"
+ const val kotlinVersion = "1.8.0"
+ const val kotlinMetadataVersion = "0.6.0"
+ const val smaliVersion = "2.2b4"
+}
+
+object Deps {
+ val asm by lazy { "org.ow2.asm:asm:${Versions.asmVersion}" }
+ val asmUtil by lazy { "org.ow2.asm:asm-util:${Versions.asmVersion}" }
+ val asmCommons by lazy { "org.ow2.asm:asm-commons:${Versions.asmVersion}" }
+ val fastUtil by lazy { "it.unimi.dsi:fastutil:${Versions.fastUtilVersion}"}
+ val gson by lazy { "com.google.code.gson:gson:${Versions.gsonVersion}"}
+ val guava by lazy { "com.google.guava:guava:${Versions.guavaVersion}" }
+ val joptSimple by lazy { "net.sf.jopt-simple:jopt-simple:${Versions.joptSimpleVersion}" }
+ val junit by lazy { "junit:junit:${Versions.junitVersion}"}
+ val kotlinMetadata by lazy {
+ "org.jetbrains.kotlinx:kotlinx-metadata-jvm:${Versions.kotlinMetadataVersion}" }
+ val kotlinStdLib by lazy { "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlinVersion}" }
+ val kotlinReflect by lazy { "org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlinVersion}" }
+ val smali by lazy { "org.smali:smali:${Versions.smaliVersion}" }
+}
diff --git a/d8_r8/gradle.properties b/d8_r8/gradle.properties
new file mode 100644
index 0000000..ef0be28
--- /dev/null
+++ b/d8_r8/gradle.properties
@@ -0,0 +1,17 @@
+# 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.
+
+org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
+kotlin.daemon.jvmargs=-Xmx3g -Dkotlin.js.compiler.legacy.force_enabled=true
+systemProp.file.encoding=UTF-8
+
+# Enable new incremental compilation
+kotlin.incremental.useClasspathSnapshot=true
+
+org.gradle.parallel=true
+org.gradle.caching=true
+
+# Do not download any jdks or detect them. We provide them
+org.gradle.java.installations.auto-detect=false
+org.gradle.java.installations.auto-download=false
diff --git a/d8_r8/keepanno/build.gradle.kts b/d8_r8/keepanno/build.gradle.kts
new file mode 100644
index 0000000..b7a2acf
--- /dev/null
+++ b/d8_r8/keepanno/build.gradle.kts
@@ -0,0 +1,21 @@
+// 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.
+
+plugins {
+ `kotlin-dsl`
+ id("dependencies-plugin")
+}
+
+java {
+ sourceSets.main.configure {
+ java.srcDir(getRoot().resolveAll("src", "keepanno", "java"))
+ }
+ sourceCompatibility = JvmCompatibility.sourceCompatibility
+ targetCompatibility = JvmCompatibility.targetCompatibility
+}
+
+dependencies {
+ compileOnly(Deps.asm)
+ compileOnly(Deps.guava)
+}
diff --git a/d8_r8/keepanno/gradle.properties b/d8_r8/keepanno/gradle.properties
new file mode 100644
index 0000000..ef0be28
--- /dev/null
+++ b/d8_r8/keepanno/gradle.properties
@@ -0,0 +1,17 @@
+# 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.
+
+org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
+kotlin.daemon.jvmargs=-Xmx3g -Dkotlin.js.compiler.legacy.force_enabled=true
+systemProp.file.encoding=UTF-8
+
+# Enable new incremental compilation
+kotlin.incremental.useClasspathSnapshot=true
+
+org.gradle.parallel=true
+org.gradle.caching=true
+
+# Do not download any jdks or detect them. We provide them
+org.gradle.java.installations.auto-detect=false
+org.gradle.java.installations.auto-download=false
diff --git a/d8_r8/keepanno/settings.gradle.kts b/d8_r8/keepanno/settings.gradle.kts
new file mode 100644
index 0000000..7b4d459
--- /dev/null
+++ b/d8_r8/keepanno/settings.gradle.kts
@@ -0,0 +1,18 @@
+// 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.
+
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "keepanno"
diff --git a/d8_r8/main/build.gradle.kts b/d8_r8/main/build.gradle.kts
new file mode 100644
index 0000000..e664753
--- /dev/null
+++ b/d8_r8/main/build.gradle.kts
@@ -0,0 +1,33 @@
+// 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.
+
+plugins {
+ `kotlin-dsl`
+ id("dependencies-plugin")
+}
+
+java {
+ sourceSets.main.configure {
+ java.srcDir(getRoot().resolveAll("src", "main", "java"))
+ resources.srcDirs(getRoot().resolveAll("third_party", "api_database", "api_database"))
+ }
+ sourceCompatibility = JvmCompatibility.sourceCompatibility
+ targetCompatibility = JvmCompatibility.targetCompatibility
+}
+
+dependencies {
+ implementation(":keepanno")
+ implementation(Deps.asm)
+ implementation(Deps.asmUtil)
+ implementation(Deps.asmCommons)
+ implementation(Deps.fastUtil)
+ implementation(Deps.gson)
+ implementation(Deps.guava)
+ implementation(Deps.joptSimple)
+ implementation(Deps.kotlinMetadata)
+}
+
+tasks.withType<JavaCompile> {
+ println("NOTE: Running with JDK: " + org.gradle.internal.jvm.Jvm.current().javaHome)
+}
diff --git a/d8_r8/main/gradle.properties b/d8_r8/main/gradle.properties
new file mode 100644
index 0000000..ef0be28
--- /dev/null
+++ b/d8_r8/main/gradle.properties
@@ -0,0 +1,17 @@
+# 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.
+
+org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
+kotlin.daemon.jvmargs=-Xmx3g -Dkotlin.js.compiler.legacy.force_enabled=true
+systemProp.file.encoding=UTF-8
+
+# Enable new incremental compilation
+kotlin.incremental.useClasspathSnapshot=true
+
+org.gradle.parallel=true
+org.gradle.caching=true
+
+# Do not download any jdks or detect them. We provide them
+org.gradle.java.installations.auto-detect=false
+org.gradle.java.installations.auto-download=false
diff --git a/d8_r8/main/settings.gradle.kts b/d8_r8/main/settings.gradle.kts
new file mode 100644
index 0000000..2d727f0
--- /dev/null
+++ b/d8_r8/main/settings.gradle.kts
@@ -0,0 +1,18 @@
+// 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.
+
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "r8"
diff --git a/d8_r8/settings.gradle.kts b/d8_r8/settings.gradle.kts
new file mode 100644
index 0000000..2feb93c
--- /dev/null
+++ b/d8_r8/settings.gradle.kts
@@ -0,0 +1,30 @@
+// 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.
+
+// TODO(X): Move this file out the repository root when old gradle is removed.
+
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "d8-r8"
+
+// This project is temporarily located in d8_r8. When moved to root, the parent
+// folder should just be removed.
+includeBuild(rootProject.projectDir.parentFile.resolve("commonBuildSrc"))
+includeBuild("keepanno")
+
+// We need to include src/main as a composite-build otherwise our test-modules
+// will compete with the test to compile the source files.
+includeBuild("main")
+includeBuild("test")
diff --git a/d8_r8/test/build.gradle.kts b/d8_r8/test/build.gradle.kts
new file mode 100644
index 0000000..34f153b
--- /dev/null
+++ b/d8_r8/test/build.gradle.kts
@@ -0,0 +1,55 @@
+// 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.
+
+plugins {
+ `kotlin-dsl`
+ id("dependencies-plugin")
+}
+
+val root = getRoot();
+
+java {
+ sourceSets.test.configure {
+ java.srcDir(root.resolveAll("src", "test", "java"))
+ }
+ sourceCompatibility = JvmCompatibility.sourceCompatibility
+ targetCompatibility = JvmCompatibility.targetCompatibility
+}
+
+// We cannot use languageVersion.set(JavaLanguageVersion.of("8")) because gradle cannot figure
+// out that the jdk is 1_8 and will try to download it.
+tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
+ kotlinOptions {
+ jvmTarget = "11"
+ }
+}
+
+
+dependencies {
+ implementation(":r8")
+ implementation(":keepanno")
+ implementation(Deps.asm)
+ implementation(Deps.gson)
+ implementation(Deps.guava)
+ implementation(Deps.junit)
+ implementation(Deps.kotlinStdLib)
+ implementation(Deps.kotlinReflect)
+ implementation(Deps.kotlinMetadata)
+ implementation(files(root.resolveAll("third_party", "ddmlib", "ddmlib.jar")))
+ implementation(
+ files(
+ root.resolveAll("third_party", "jdwp-tests", "apache-harmony-jdwp-tests-host.jar")))
+ implementation(files(root.resolveAll("third_party", "jasmin", "jasmin-2.4.jar")))
+ implementation(Deps.fastUtil)
+ implementation(Deps.smali)
+ implementation(Deps.asmUtil)
+}
+
+tasks.named("test") {
+ dependsOn(gradle.includedBuild("tests_java_8").task(":compileJava"))
+}
+
+tasks.withType<Test> {
+ environment("USE_NEW_GRADLE_SETUP", "true")
+}
diff --git a/d8_r8/test/gradle.properties b/d8_r8/test/gradle.properties
new file mode 100644
index 0000000..ef0be28
--- /dev/null
+++ b/d8_r8/test/gradle.properties
@@ -0,0 +1,17 @@
+# 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.
+
+org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
+kotlin.daemon.jvmargs=-Xmx3g -Dkotlin.js.compiler.legacy.force_enabled=true
+systemProp.file.encoding=UTF-8
+
+# Enable new incremental compilation
+kotlin.incremental.useClasspathSnapshot=true
+
+org.gradle.parallel=true
+org.gradle.caching=true
+
+# Do not download any jdks or detect them. We provide them
+org.gradle.java.installations.auto-detect=false
+org.gradle.java.installations.auto-download=false
diff --git a/d8_r8/test/settings.gradle.kts b/d8_r8/test/settings.gradle.kts
new file mode 100644
index 0000000..3138d52
--- /dev/null
+++ b/d8_r8/test/settings.gradle.kts
@@ -0,0 +1,15 @@
+// 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.
+
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "r8-tests"
+
+val root = rootProject.projectDir.parentFile
+includeBuild(root.resolve("test_modules").resolve("tests_java_8"))
diff --git a/d8_r8/test_modules/tests_java_8/build.gradle.kts b/d8_r8/test_modules/tests_java_8/build.gradle.kts
new file mode 100644
index 0000000..9908599
--- /dev/null
+++ b/d8_r8/test_modules/tests_java_8/build.gradle.kts
@@ -0,0 +1,88 @@
+// 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.
+
+import org.gradle.api.JavaVersion
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+ `kotlin-dsl`
+ `java-library`
+ id("dependencies-plugin")
+}
+
+val root = getRoot()
+
+java {
+ sourceSets.main.configure {
+ java.srcDir(root.resolveAll("src", "test", "java"))
+ }
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+
+// We cannot use languageVersion.set(JavaLanguageVersion.of("8")) because gradle cannot figure
+// out that the jdk is 1_8 and will try to download it.
+tasks.withType<KotlinCompile> {
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+}
+
+// The test module compilation depends on main and keep anno output, but we cannot directly
+// reference the task we only obtain a task reference. To obtain the actual reference by creating
+// a dummy.
+tasks.register("dummy-keepanno-reference") {
+ dependsOn(gradle.includedBuild("keepanno").task(":jar"))
+}
+val keepAnnoTask = tasks.getByName("dummy-keepanno-reference")
+ .taskDependencies
+ .getDependencies(tasks.getByName("dummy-keepanno-reference"))
+ .iterator()
+ .next()
+
+tasks.register("dummy-r8-reference") {
+ dependsOn(gradle.includedBuild("main").task(":jar"))
+}
+val r8Task = tasks.getByName("dummy-r8-reference")
+ .taskDependencies
+ .getDependencies(tasks.getByName("dummy-r8-reference"))
+ .iterator()
+ .next()
+
+dependencies {
+ implementation(keepAnnoTask.outputs.files)
+ implementation(r8Task.outputs.files)
+ implementation(Deps.asm)
+ implementation(Deps.gson)
+ implementation(Deps.guava)
+ implementation(Deps.junit)
+ implementation(Deps.kotlinStdLib)
+ implementation(Deps.kotlinReflect)
+ implementation(Deps.kotlinMetadata)
+ implementation(files(root.resolveAll("third_party", "ddmlib", "ddmlib.jar")))
+ implementation(
+ files(
+ root.resolveAll("third_party", "jdwp-tests", "apache-harmony-jdwp-tests-host.jar")))
+ implementation(files(root.resolveAll("third_party", "jasmin", "jasmin-2.4.jar")))
+ implementation(Deps.fastUtil)
+ implementation(Deps.smali)
+ implementation(Deps.asmUtil)
+}
+
+tasks.withType<JavaCompile> {
+ dependsOn(keepAnnoTask)
+ dependsOn(r8Task)
+ options.setFork(true)
+ options.forkOptions.memoryMaximumSize = "3g"
+ options.forkOptions.jvmArgs = listOf(
+ "-Xss256m",
+ // Set the bootclass path so compilation is consistent with 1.8 target compatibility.
+ "-Xbootclasspath/a:third_party/openjdk/openjdk-rt-1.8/rt.jar")
+}
+
+tasks.withType<KotlinCompile> {
+ dependsOn(keepAnnoTask)
+ dependsOn(r8Task)
+}
diff --git a/d8_r8/test_modules/tests_java_8/gradle.properties b/d8_r8/test_modules/tests_java_8/gradle.properties
new file mode 100644
index 0000000..ef0be28
--- /dev/null
+++ b/d8_r8/test_modules/tests_java_8/gradle.properties
@@ -0,0 +1,17 @@
+# 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.
+
+org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
+kotlin.daemon.jvmargs=-Xmx3g -Dkotlin.js.compiler.legacy.force_enabled=true
+systemProp.file.encoding=UTF-8
+
+# Enable new incremental compilation
+kotlin.incremental.useClasspathSnapshot=true
+
+org.gradle.parallel=true
+org.gradle.caching=true
+
+# Do not download any jdks or detect them. We provide them
+org.gradle.java.installations.auto-detect=false
+org.gradle.java.installations.auto-download=false
diff --git a/d8_r8/test_modules/tests_java_8/settings.gradle.kts b/d8_r8/test_modules/tests_java_8/settings.gradle.kts
new file mode 100644
index 0000000..290b820
--- /dev/null
+++ b/d8_r8/test_modules/tests_java_8/settings.gradle.kts
@@ -0,0 +1,28 @@
+// 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.
+
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+rootProject.name = "r8-java8-tests"
+
+val d8Root = rootProject.projectDir.parentFile.parentFile
+val root = d8Root.parentFile
+
+includeBuild(root.resolve("commonBuildSrc"))
+includeBuild(d8Root.resolve("keepanno"))
+
+// We need to include src/main as a composite-build otherwise our test-modules
+// will compete with the test to compile the source files.
+includeBuild(d8Root.resolve("main"))
diff --git a/gradle.properties b/gradle.properties
index 41fabcc..b2b8d2a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,4 +2,16 @@
# 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.
-org.gradle.jvmargs=-Xmx2048M
\ No newline at end of file
+org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8
+kotlin.daemon.jvmargs=-Xmx3g -Dkotlin.js.compiler.legacy.force_enabled=true
+systemProp.file.encoding=UTF-8
+
+# Enable new incremental compilation
+kotlin.incremental.useClasspathSnapshot=true
+
+org.gradle.parallel=true
+org.gradle.caching=true
+
+# Do not download any jdks or detect them. We provide them
+org.gradle.java.installations.auto-detect=false
+org.gradle.java.installations.auto-download=false
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index 4d1269c..f251ecb 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -21,6 +21,7 @@
import com.android.tools.r8.utils.DumpInputFlags;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ProgramConsumerUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.ThreadUtils;
@@ -154,6 +155,9 @@
.setOptimizeMultidexForLinearAlloc(isOptimizeMultidexForLinearAlloc())
.setThreadCount(getThreadCount())
.setDesugarState(getDesugarState())
+ .setArtProfileProviders(
+ ListUtils.map(
+ getArtProfilesForRewriting(), ArtProfileForRewriting::getArtProfileProvider))
.setStartupProfileProviders(getStartupProfileProviders());
if (getAndroidPlatformBuild()) {
builder.setAndroidPlatformBuild(true);
diff --git a/src/main/java/com/android/tools/r8/ClassFileConsumer.java b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
index fa3e5c4..79330fb 100644
--- a/src/main/java/com/android/tools/r8/ClassFileConsumer.java
+++ b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
@@ -4,6 +4,7 @@
package com.android.tools.r8;
import com.android.tools.r8.utils.ArchiveBuilder;
+import com.android.tools.r8.utils.ClassFileConsumerDataImpl;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.DirectoryBuilder;
import com.android.tools.r8.utils.OutputBuilder;
@@ -36,22 +37,28 @@
* {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown,
* then the compiler guaranties to exit with an error.
*
- * <p>The {@link ByteDataView} {@param data} object can only be assumed valid during the duration
- * of the accept. If the bytes are needed beyond that, a copy must be made elsewhere.
+ * <p>The {@link ByteDataView} obtained by way of {@param data} object can only be assumed valid
+ * during the duration of the accept. If the bytes are needed beyond that, a copy must be made
+ * elsewhere.
*
- * @param data Java class-file encoded data.
- * @param descriptor Class descriptor of the class the data pertains to.
- * @param handler Diagnostics handler for reporting.
+ * @param data Java class-file encoded data and its meta-data.
*/
- void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler);
+ default void acceptClassFile(ClassFileConsumerData data) {
+ accept(data.getByteDataView(), data.getClassDescriptor(), data.getDiagnosticsHandler());
+ }
+
+ @Deprecated
+ default void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ acceptClassFile(new ClassFileConsumerDataImpl(data, descriptor, handler));
+ }
/** Empty consumer to request the production of the resource but ignore its value. */
static ClassFileConsumer emptyConsumer() {
return ForwardingConsumer.EMPTY_CONSUMER;
}
- /** Forwarding consumer to delegate to an optional existing consumer. */
@Keep
+ @Deprecated
class ForwardingConsumer implements ClassFileConsumer {
private static final ClassFileConsumer EMPTY_CONSUMER = new ForwardingConsumer(null);
@@ -68,9 +75,9 @@
}
@Override
- public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ public void acceptClassFile(ClassFileConsumerData data) {
if (consumer != null) {
- consumer.accept(data, descriptor, handler);
+ consumer.acceptClassFile(data);
}
}
@@ -117,9 +124,12 @@
}
@Override
- public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
- super.accept(data, descriptor, handler);
- outputBuilder.addFile(DescriptorUtils.getClassFileName(descriptor), data, handler);
+ public void acceptClassFile(ClassFileConsumerData data) {
+ super.acceptClassFile(data);
+ outputBuilder.addFile(
+ DescriptorUtils.getClassFileName(data.getClassDescriptor()),
+ data.getByteDataView(),
+ data.getDiagnosticsHandler());
}
@Override
@@ -194,9 +204,12 @@
}
@Override
- public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
- super.accept(data, descriptor, handler);
- outputBuilder.addFile(DescriptorUtils.getClassFileName(descriptor), data, handler);
+ public void acceptClassFile(ClassFileConsumerData data) {
+ super.acceptClassFile(data);
+ outputBuilder.addFile(
+ DescriptorUtils.getClassFileName(data.getClassDescriptor()),
+ data.getByteDataView(),
+ data.getDiagnosticsHandler());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ClassFileConsumerData.java b/src/main/java/com/android/tools/r8/ClassFileConsumerData.java
new file mode 100644
index 0000000..eeef801
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ClassFileConsumerData.java
@@ -0,0 +1,26 @@
+// 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;
+
+/** Data provided in the primary callback of {@link ClassFileConsumer}. */
+@Keep
+public interface ClassFileConsumerData {
+
+ /**
+ * View of the Java class-file encoded data.
+ *
+ * <p>The obtained {@link ByteDataView} object can only be assumed valid during the duration of
+ * the accept method. If the bytes are needed beyond that, a copy must be made elsewhere.
+ */
+ ByteDataView getByteDataView();
+
+ /** Copy of the bytes for the Java class-file encoded data. */
+ byte[] getByteDataCopy();
+
+ /** Class descriptor of the class the data pertains to. */
+ String getClassDescriptor();
+
+ /** Diagnostics handler for reporting. */
+ DiagnosticsHandler getDiagnosticsHandler();
+}
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index c57bc22..85a0fbf 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -53,7 +53,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -441,12 +440,14 @@
private final List<ProgramResource> resources = new ArrayList<>();
@Override
- public synchronized void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
+ public synchronized void acceptDexIndexedFile(DexIndexedConsumerData data) {
// TODO(b/154106502): Map Origin information.
resources.add(
ProgramResource.fromBytes(
- Origin.unknown(), ProgramResource.Kind.DEX, data.copyByteData(), descriptors));
+ Origin.unknown(),
+ ProgramResource.Kind.DEX,
+ data.getByteDataCopy(),
+ data.getClassDescriptors()));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index a12e730..13c12a2 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -402,12 +402,16 @@
&& isMinApiLevelSet()) {
reporter.error("Compiling to CF with --min-api and --no-desugaring is not supported");
}
- if (!getStartupProfileProviders().isEmpty()
- && getMinApiLevel() < AndroidApiLevel.L.getLevel()) {
- reporter.error(
- "D8 startup layout requires native multi dex support (API level "
- + AndroidApiLevel.L.getLevel()
- + " and above)");
+ if (!getStartupProfileProviders().isEmpty()) {
+ if (intermediate) {
+ reporter.error("D8 startup layout is not supported in intermediate mode");
+ }
+ if (getMinApiLevel() < AndroidApiLevel.L.getLevel()) {
+ reporter.error(
+ "D8 startup layout requires native multi dex support (API level "
+ + AndroidApiLevel.L.getLevel()
+ + " and above)");
+ }
}
super.validate();
}
diff --git a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
index 1675cb2..68e6f12 100644
--- a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
+++ b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
@@ -34,7 +34,7 @@
@KeepForSubclassing
public interface DexFilePerClassFileConsumer extends ProgramConsumer, ByteBufferProvider {
- static final boolean SHOULD_COMBINE_SYNTHETIC_CLASSES = true;
+ boolean SHOULD_COMBINE_SYNTHETIC_CLASSES = true;
/**
* Callback to receive DEX data for a single Java class-file input and its companion classes.
@@ -42,24 +42,30 @@
* <p>There is no guaranteed order and files might be written concurrently.
*
* <p>The consumer is expected not to throw, but instead report any errors via the diagnostics
- * {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown,
- * then the compiler guaranties to exit with an error.
+ * {@link DiagnosticsHandler} in the callback data. If an error is reported via handler and no
+ * exceptions are thrown, then the compiler guaranties to exit with an error.
*
- * <p>The {@link ByteDataView} {@param data} object can only be assumed valid during the duration
- * of the accept. If the bytes are needed beyond that, a copy must be made elsewhere.
- *
- * @param primaryClassDescriptor Class descriptor of the class from the input class-file.
- * @param data DEX encoded data in a ByteDataView wrapper.
- * @param descriptors Class descriptors for all classes defined in the DEX data.
- * @param handler Diagnostics handler for reporting.
+ * <p>The {@link ByteDataView} obtained from the {@param data} object can only be assumed valid
+ * during the duration of the accept. If the bytes are needed beyond that, a copy must be made
+ * elsewhere.
*/
+ default void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ accept(
+ data.getPrimaryClassDescriptor(),
+ data.getByteDataView(),
+ data.getClassDescriptors(),
+ data.getDiagnosticsHandler());
+ }
+
+ // Any new implementation should not use or call the deprecated accept method.
+ @Deprecated
default void accept(
String primaryClassDescriptor,
ByteDataView data,
Set<String> descriptors,
DiagnosticsHandler handler) {
- // To avoid breaking binary compatiblity, old consumers not implementing the new API will be
- // forwarded to. New consumers must implement the accept on ByteDataView.
+ // To avoid breaking binary compatibility, old consumers not implementing the new API will be
+ // forwarded to. New consumers must implement the accept method on the data object.
accept(primaryClassDescriptor, data.copyByteData(), descriptors, handler);
}
@@ -92,8 +98,8 @@
return ForwardingConsumer.EMPTY_CONSUMER;
}
- /** Forwarding consumer to delegate to an optional existing consumer. */
@Keep
+ @Deprecated
class ForwardingConsumer implements DexFilePerClassFileConsumer {
private static final DexFilePerClassFileConsumer EMPTY_CONSUMER = new ForwardingConsumer(null);
@@ -110,13 +116,9 @@
}
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
if (consumer != null) {
- consumer.accept(primaryClassDescriptor, data, descriptors, handler);
+ consumer.acceptDexFile(data);
}
}
@@ -178,13 +180,12 @@
}
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- super.accept(primaryClassDescriptor, data, descriptors, handler);
- outputBuilder.addFile(getDexFileName(primaryClassDescriptor), data, handler);
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ super.acceptDexFile(data);
+ outputBuilder.addFile(
+ getDexFileName(data.getPrimaryClassDescriptor()),
+ data.getByteDataView(),
+ data.getDiagnosticsHandler());
}
@Override
@@ -262,13 +263,12 @@
}
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- super.accept(primaryClassDescriptor, data, descriptors, handler);
- outputBuilder.addFile(getDexFileName(primaryClassDescriptor), data, handler);
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ super.acceptDexFile(data);
+ outputBuilder.addFile(
+ getDexFileName(data.getPrimaryClassDescriptor()),
+ data.getByteDataView(),
+ data.getDiagnosticsHandler());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java
new file mode 100644
index 0000000..fba6b8d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java
@@ -0,0 +1,35 @@
+// 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;
+
+import java.util.Set;
+
+/** Data provided in the primary callback of {@link DexFilePerClassFileConsumer}. */
+@Keep
+public interface DexFilePerClassFileConsumerData {
+
+ /** Class descriptor of the class from the input class-file. */
+ String getPrimaryClassDescriptor();
+
+ /** DEX encoded data in a ByteDataView wrapper. */
+ ByteDataView getByteDataView();
+
+ /** Copy of the bytes for the DEX encoded data. */
+ byte[] getByteDataCopy();
+
+ /** Class descriptors for all classes defined in the DEX data. */
+ Set<String> getClassDescriptors();
+
+ /** Diagnostics handler for reporting. */
+ DiagnosticsHandler getDiagnosticsHandler();
+
+ /**
+ * Class descriptor of the primary-class's synthetic context.
+ *
+ * <p>If primary class is a compiler-synthesized class (i.e. it is an input that was synthesized
+ * by a prior D8 intermediate compilation) then the value is the descriptor of the class that
+ * caused the primary class to be synthesized. The value is null in all other cases.
+ */
+ String getSynthesizingContextForPrimaryClass();
+}
diff --git a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
index 39f5b2e..cbccf59 100644
--- a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
+++ b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
@@ -46,17 +46,22 @@
* <p>There is no guaranteed order and files might be written concurrently.
*
* <p>The consumer is expected not to throw, but instead report any errors via the diagnostics
- * {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown,
- * then the compiler guaranties to exit with an error.
+ * {@link DiagnosticsHandler} in the callback data. If an error is reported via handler and no
+ * exceptions are thrown, then the compiler guaranties to exit with an error.
*
- * <p>The {@link ByteDataView} {@param data} object can only be assumed valid during the duration
- * of the accept. If the bytes are needed beyond that, a copy must be made elsewhere.
- *
- * @param fileIndex Index of the DEX file for multi-dexing. Files are zero-indexed.
- * @param data DEX encoded data in a ByteDataView wrapper.
- * @param descriptors Class descriptors for all classes defined in the DEX data.
- * @param handler Diagnostics handler for reporting.
+ * <p>The {@link ByteDataView} obtained from the {@param data} object can only be assumed valid
+ * during the duration of the accept. If the bytes are needed beyond that, a copy must be made
+ * elsewhere.
*/
+ default void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ accept(
+ data.getFileIndex(),
+ data.getByteDataView(),
+ data.getClassDescriptors(),
+ data.getDiagnosticsHandler());
+ }
+
+ @Deprecated
default void accept(
int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
// To avoid breaking binary compatiblity, old consumers not implementing the new API will be
@@ -77,8 +82,8 @@
return ForwardingConsumer.EMPTY_CONSUMER;
}
- /** Forwarding consumer to delegate to an optional existing consumer. */
@Keep
+ @Deprecated
class ForwardingConsumer implements DexIndexedConsumer {
private static final DexIndexedConsumer EMPTY_CONSUMER = new ForwardingConsumer(null);
@@ -95,10 +100,9 @@
}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
if (consumer != null) {
- consumer.accept(fileIndex, data, descriptors, handler);
+ consumer.acceptDexIndexedFile(data);
}
}
@@ -150,11 +154,13 @@
}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
- super.accept(fileIndex, data, descriptors, handler);
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ super.acceptDexIndexedFile(data);
outputBuilder.addIndexedClassFile(
- fileIndex, DexUtils.getDefaultDexFileName(fileIndex), data, handler);
+ data.getFileIndex(),
+ DexUtils.getDefaultDexFileName(data.getFileIndex()),
+ data.getByteDataView(),
+ data.getDiagnosticsHandler());
}
@Override
@@ -245,15 +251,17 @@
}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
- super.accept(fileIndex, data, descriptors, handler);
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ super.acceptDexIndexedFile(data);
try {
prepareDirectory();
} catch (IOException e) {
- handler.error(new ExceptionDiagnostic(e, new PathOrigin(directory)));
+ data.getDiagnosticsHandler().error(new ExceptionDiagnostic(e, new PathOrigin(directory)));
}
- outputBuilder.addFile(DexUtils.getDefaultDexFileName(fileIndex), data, handler);
+ outputBuilder.addFile(
+ DexUtils.getDefaultDexFileName(data.getFileIndex()),
+ data.getByteDataView(),
+ data.getDiagnosticsHandler());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/DexIndexedConsumerData.java b/src/main/java/com/android/tools/r8/DexIndexedConsumerData.java
new file mode 100644
index 0000000..1c46f8c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/DexIndexedConsumerData.java
@@ -0,0 +1,26 @@
+// 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;
+
+import java.util.Set;
+
+/** Data provided in the primary callback of {@link DexIndexedConsumer}. */
+@Keep
+public interface DexIndexedConsumerData {
+
+ /** Index of the DEX file for multi-dexing (Files are zero-indexed). */
+ int getFileIndex();
+
+ /** DEX encoded data in a ByteDataView wrapper. */
+ ByteDataView getByteDataView();
+
+ /** Copy of the bytes for the DEX encoded data. */
+ byte[] getByteDataCopy();
+
+ /** Class descriptors for all classes defined in the DEX data. */
+ Set<String> getClassDescriptors();
+
+ /** Diagnostics handler for reporting. */
+ DiagnosticsHandler getDiagnosticsHandler();
+}
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index ebe84b2..6bac5df 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -164,7 +164,13 @@
@Override
List<ArtProfileForRewriting> getArtProfilesForRewriting() {
- return getD8Command().getArtProfilesForRewriting();
+ if (getD8Command() != null) {
+ return getD8Command().getArtProfilesForRewriting();
+ }
+ if (getR8Command() != null) {
+ return getR8Command().getArtProfilesForRewriting();
+ }
+ return Collections.emptyList();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 99cb304..d0daf58 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -58,6 +58,8 @@
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.DexFilePerClassFileConsumerDataImpl;
+import com.android.tools.r8.utils.DexIndexedConsumerDataImpl;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.InternalGlobalSyntheticsProgramConsumer;
@@ -586,13 +588,14 @@
ProgramConsumer consumer;
ByteBufferProvider byteBufferProvider;
+ String primaryClassDescriptor = virtualFile.getPrimaryClassDescriptor();
if (globalSyntheticFiles != null && globalSyntheticFiles.contains(virtualFile)) {
consumer = globalsSyntheticsConsumer;
byteBufferProvider = globalsSyntheticsConsumer;
} else if (programConsumer != null) {
consumer = programConsumer;
byteBufferProvider = programConsumer;
- } else if (virtualFile.getPrimaryClassDescriptor() != null) {
+ } else if (primaryClassDescriptor != null) {
consumer = options.getDexFilePerClassFileConsumer();
byteBufferProvider = options.getDexFilePerClassFileConsumer();
} else {
@@ -620,14 +623,18 @@
timing.begin("Pass bytes to consumer");
if (consumer instanceof DexFilePerClassFileConsumer) {
((DexFilePerClassFileConsumer) consumer)
- .accept(
- virtualFile.getPrimaryClassDescriptor(),
- data,
- virtualFile.getClassDescriptors(),
- options.reporter);
+ .acceptDexFile(
+ new DexFilePerClassFileConsumerDataImpl(
+ primaryClassDescriptor,
+ virtualFile.getPrimaryClassSynthesizingContextDescriptor(),
+ data,
+ virtualFile.getClassDescriptors(),
+ options.reporter));
} else {
((DexIndexedConsumer) consumer)
- .accept(virtualFile.getId(), data, virtualFile.getClassDescriptors(), options.reporter);
+ .acceptDexIndexedFile(
+ new DexIndexedConsumerDataImpl(
+ virtualFile.getId(), data, virtualFile.getClassDescriptors(), options.reporter));
}
timing.end();
// Release use of the backing buffer now that accept has returned.
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
index 0a81bd2..cdb74b5 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.utils.BitUtils;
+import com.android.tools.r8.utils.DexIndexedConsumerDataImpl;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ThreadUtils;
@@ -172,7 +173,9 @@
if (consumer instanceof DexFilePerClassFileConsumer) {
assert false;
} else {
- ((DexIndexedConsumer) consumer).accept(0, data, Sets.newIdentityHashSet(), options.reporter);
+ ((DexIndexedConsumer) consumer)
+ .acceptDexIndexedFile(
+ new DexIndexedConsumerDataImpl(0, data, Sets.newIdentityHashSet(), options.reporter));
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index 6d1af5d..692192d 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -49,7 +49,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
@@ -73,6 +72,7 @@
private final StartupOrder startupOrder;
private final DexString primaryClassDescriptor;
+ private final DexString primaryClassSynthesizingContextDescriptor;
private DebugRepresentation debugRepresentation;
VirtualFile(int id, AppView<?> appView) {
@@ -102,12 +102,23 @@
this.id = id;
this.indexedItems = new VirtualFileIndexedItemCollection(appView);
this.transaction = new IndexedItemTransaction(indexedItems, appView);
- this.primaryClassDescriptor =
- primaryClass == null
- ? null
- : appView.getNamingLens().lookupClassDescriptor(primaryClass.type);
this.featureSplit = featureSplit;
this.startupOrder = startupOrder;
+ if (primaryClass == null) {
+ primaryClassDescriptor = null;
+ primaryClassSynthesizingContextDescriptor = null;
+ } else {
+ DexType type = primaryClass.getType();
+ primaryClassDescriptor = appView.getNamingLens().lookupClassDescriptor(type);
+ Collection<DexType> contexts = appView.getSyntheticItems().getSynthesizingContextTypes(type);
+ if (contexts.size() == 1) {
+ primaryClassSynthesizingContextDescriptor =
+ appView.getNamingLens().lookupClassDescriptor(contexts.iterator().next());
+ } else {
+ assert contexts.isEmpty();
+ primaryClassSynthesizingContextDescriptor = null;
+ }
+ }
}
public int getId() {
@@ -135,6 +146,12 @@
return primaryClassDescriptor == null ? null : primaryClassDescriptor.toString();
}
+ public String getPrimaryClassSynthesizingContextDescriptor() {
+ return primaryClassSynthesizingContextDescriptor == null
+ ? null
+ : primaryClassSynthesizingContextDescriptor.toString();
+ }
+
public void setDebugRepresentation(DebugRepresentation debugRepresentation) {
assert debugRepresentation != null;
assert this.debugRepresentation == null;
@@ -319,35 +336,36 @@
@Override
public List<VirtualFile> run() {
- HashMap<DexProgramClass, VirtualFile> files = new HashMap<>();
- Collection<DexProgramClass> synthetics = new ArrayList<>();
+ Map<DexType, VirtualFile> files = new IdentityHashMap<>();
+ Map<DexType, List<DexProgramClass>> derivedSynthetics = new LinkedHashMap<>();
// Assign dedicated virtual files for all program classes.
for (DexProgramClass clazz : classes) {
- // TODO(b/181636450): Simplify this making use of the assumption that synthetics are never
- // duplicated.
- if (!combineSyntheticClassesWithPrimaryClass
- || !appView.getSyntheticItems().isSyntheticClass(clazz)) {
- VirtualFile file = new VirtualFile(virtualFiles.size(), appView, clazz);
- virtualFiles.add(file);
- file.addClass(clazz);
- files.put(clazz, file);
- // Commit this early, so that we do not keep the transaction state around longer than
- // needed and clear the underlying sets.
- file.commitTransaction();
- } else {
- synthetics.add(clazz);
+ if (combineSyntheticClassesWithPrimaryClass) {
+ DexType inputContextType =
+ appView
+ .getSyntheticItems()
+ .getSynthesizingInputContext(clazz.getType(), appView.options());
+ if (inputContextType != null && inputContextType != clazz.getType()) {
+ derivedSynthetics.computeIfAbsent(inputContextType, k -> new ArrayList<>()).add(clazz);
+ continue;
+ }
}
- }
- for (DexProgramClass synthetic : synthetics) {
- Collection<DexType> synthesizingContexts =
- appView.getSyntheticItems().getSynthesizingContextTypes(synthetic.getType());
- assert synthesizingContexts.size() == 1;
- DexProgramClass inputType =
- appView.definitionForProgramType(synthesizingContexts.iterator().next());
- VirtualFile file = files.get(inputType);
- file.addClass(synthetic);
+ VirtualFile file = new VirtualFile(virtualFiles.size(), appView, clazz);
+ virtualFiles.add(file);
+ file.addClass(clazz);
+ files.put(clazz.getType(), file);
+ // Commit this early, so that we do not keep the transaction state around longer than
+ // needed and clear the underlying sets.
file.commitTransaction();
}
+ derivedSynthetics.forEach(
+ (inputContextType, synthetics) -> {
+ VirtualFile file = files.get(inputContextType);
+ for (DexProgramClass synthetic : synthetics) {
+ file.addClass(synthetic);
+ file.commitTransaction();
+ }
+ });
return virtualFiles;
}
}
diff --git a/src/main/java/com/android/tools/r8/dump/DumpOptions.java b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
index 2ecf1d3..0c538fa 100644
--- a/src/main/java/com/android/tools/r8/dump/DumpOptions.java
+++ b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.features.FeatureSplitConfiguration;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
+import com.android.tools.r8.profile.art.ArtProfileProvider;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.startup.StartupProfileProvider;
@@ -69,6 +70,7 @@
private final FeatureSplitConfiguration featureSplitConfiguration;
private final ProguardConfiguration proguardConfiguration;
private final List<ProguardConfigurationRule> mainDexKeepRules;
+ private final Collection<ArtProfileProvider> artProfileProviders;
private final Collection<StartupProfileProvider> startupProfileProviders;
private final boolean enableMissingLibraryApiModeling;
private final boolean isAndroidPlatformBuild;
@@ -98,6 +100,7 @@
FeatureSplitConfiguration featureSplitConfiguration,
ProguardConfiguration proguardConfiguration,
List<ProguardConfigurationRule> mainDexKeepRules,
+ Collection<ArtProfileProvider> artProfileProviders,
Collection<StartupProfileProvider> startupProfileProviders,
boolean enableMissingLibraryApiModeling,
boolean isAndroidPlatformBuild,
@@ -120,6 +123,7 @@
this.featureSplitConfiguration = featureSplitConfiguration;
this.proguardConfiguration = proguardConfiguration;
this.mainDexKeepRules = mainDexKeepRules;
+ this.artProfileProviders = artProfileProviders;
this.startupProfileProviders = startupProfileProviders;
this.enableMissingLibraryApiModeling = enableMissingLibraryApiModeling;
this.isAndroidPlatformBuild = isAndroidPlatformBuild;
@@ -296,6 +300,14 @@
return mainDexKeepRules;
}
+ public boolean hasArtProfileProviders() {
+ return artProfileProviders != null && !artProfileProviders.isEmpty();
+ }
+
+ public Collection<ArtProfileProvider> getArtProfileProviders() {
+ return artProfileProviders;
+ }
+
public boolean hasStartupProfileProviders() {
return startupProfileProviders != null && !startupProfileProviders.isEmpty();
}
@@ -331,6 +343,7 @@
private FeatureSplitConfiguration featureSplitConfiguration;
private ProguardConfiguration proguardConfiguration;
private List<ProguardConfigurationRule> mainDexKeepRules;
+ private Collection<ArtProfileProvider> artProfileProviders;
private Collection<StartupProfileProvider> startupProfileProviders;
private boolean enableMissingLibraryApiModeling = false;
@@ -437,6 +450,11 @@
return this;
}
+ public Builder setArtProfileProviders(Collection<ArtProfileProvider> artProfileProviders) {
+ this.artProfileProviders = artProfileProviders;
+ return this;
+ }
+
public Builder setStartupProfileProviders(
Collection<StartupProfileProvider> startupProfileProviders) {
this.startupProfileProviders = startupProfileProviders;
@@ -497,6 +515,7 @@
featureSplitConfiguration,
proguardConfiguration,
mainDexKeepRules,
+ artProfileProviders,
startupProfileProviders,
enableMissingLibraryApiModeling,
isAndroidPlatformBuild,
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 5ab8746..ec98db1 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -3,7 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter;
+import com.android.tools.r8.DesugarGraphConsumer;
+import com.android.tools.r8.origin.GlobalSyntheticOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.MainDexInfo;
@@ -87,7 +88,7 @@
return new AppInfo(app, syntheticItems, mainDexInfo, new BooleanBox());
}
- protected InternalOptions options() {
+ public InternalOptions options() {
return app.options;
}
@@ -174,19 +175,40 @@
}
DexClass definition = definitionFor(type);
if (definition != null && !definition.isLibraryClass() && !dependent.isLibraryClass()) {
- InterfaceMethodRewriter.reportDependencyEdge(dependent, definition, this);
+ reportDependencyEdge(dependent, definition);
}
return definition;
}
- public DexProgramClass unsafeDirectProgramTypeLookup(DexType type) {
- return app.programDefinitionFor(type);
+ public void reportDependencyEdge(DexClass dependent, DexClass dependency) {
+ assert !dependent.isLibraryClass();
+ assert !dependency.isLibraryClass();
+ DesugarGraphConsumer consumer = options().desugarGraphConsumer;
+ if (consumer == null) {
+ return;
+ }
+ Origin dependencyOrigin = dependency.getOrigin();
+ Collection<Origin> dependentOrigins =
+ getSyntheticItems().getSynthesizingOrigin(dependent.getType());
+ if (dependentOrigins.isEmpty()) {
+ reportDependencyEdge(consumer, dependencyOrigin, dependent.getOrigin());
+ } else {
+ for (Origin dependentOrigin : dependentOrigins) {
+ reportDependencyEdge(consumer, dependencyOrigin, dependentOrigin);
+ }
+ }
}
- public Origin originFor(DexType type) {
- assert checkIfObsolete();
- DexClass definition = app.definitionFor(type);
- return definition == null ? Origin.unknown() : definition.origin;
+ private void reportDependencyEdge(
+ DesugarGraphConsumer consumer, Origin dependencyOrigin, Origin dependentOrigin) {
+ if (dependencyOrigin == GlobalSyntheticOrigin.instance()
+ || dependentOrigin == GlobalSyntheticOrigin.instance()) {
+ // D8/R8 does not report edges to synthetic classes that D8/R8 generates.
+ return;
+ }
+ if (dependentOrigin != dependencyOrigin) {
+ consumer.accept(dependentOrigin, dependencyOrigin);
+ }
}
/**
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index fe3a2b4..40e5b9f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -101,13 +101,24 @@
if (appView.options().enableTryWithResourcesDesugaring()) {
desugarings.add(new TwrInstructionDesugaring(appView));
}
+ recordRewriter = RecordDesugaring.create(appView);
+ if (recordRewriter != null) {
+ desugarings.add(recordRewriter);
+ }
+ StringConcatInstructionDesugaring stringConcatDesugaring =
+ new StringConcatInstructionDesugaring(appView);
+ desugarings.add(stringConcatDesugaring);
+ LambdaInstructionDesugaring lambdaDesugaring = new LambdaInstructionDesugaring(appView);
+ desugarings.add(lambdaDesugaring);
interfaceMethodRewriter =
InterfaceMethodRewriter.create(
appView,
SetUtils.newImmutableSetExcludingNullItems(
alwaysThrowingInstructionDesugaring,
backportedMethodRewriter,
- desugaredLibraryRetargeter));
+ desugaredLibraryRetargeter),
+ SetUtils.newImmutableSetExcludingNullItems(
+ lambdaDesugaring, stringConcatDesugaring, recordRewriter));
if (interfaceMethodRewriter != null) {
desugarings.add(interfaceMethodRewriter);
}
@@ -124,7 +135,6 @@
if (desugaredLibraryAPIConverter != null) {
desugarings.add(desugaredLibraryAPIConverter);
}
- desugarings.add(new LambdaInstructionDesugaring(appView));
desugarings.add(new ConstantDynamicInstructionDesugaring(appView));
desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
if (appView.options().isGeneratingClassFiles()) {
@@ -132,7 +142,6 @@
assert nestBasedAccessDesugaring != null;
desugarings.add(new InvokeToPrivateRewriter());
}
- desugarings.add(new StringConcatInstructionDesugaring(appView));
if (appView.options().shouldDesugarBufferCovariantReturnType()) {
desugarings.add(new BufferCovariantReturnTypeRewriter(appView));
}
@@ -142,10 +151,6 @@
if (nestBasedAccessDesugaring != null) {
desugarings.add(nestBasedAccessDesugaring);
}
- this.recordRewriter = RecordDesugaring.create(appView);
- if (recordRewriter != null) {
- desugarings.add(recordRewriter);
- }
VarHandleDesugaring varHandleDesugaring = VarHandleDesugaring.create(appView);
if (varHandleDesugaring != null) {
desugarings.add(varHandleDesugaring);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 7695f1d..6bc5e1d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -9,10 +9,10 @@
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.NONE;
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceMethodDesugaringMode;
-import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfInvokeDynamic;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfo;
@@ -40,8 +40,6 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.icce.AlwaysThrowingInstructionDesugaring;
import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
-import com.android.tools.r8.ir.desugar.lambda.LambdaInstructionDesugaring;
-import com.android.tools.r8.ir.desugar.stringconcat.StringConcatInstructionDesugaring;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
@@ -102,8 +100,9 @@
// Caches default interface method info for already processed interfaces.
private final Map<DexType, DefaultMethodsHelper.Collection> cache = new ConcurrentHashMap<>();
- // This is used to filter out double desugaring on backported methods.
- private final Set<CfInstructionDesugaring> precedingDesugarings;
+ // This is used to filter out double desugaring.
+ private final Set<CfInstructionDesugaring> precedingDesugaringsForInvoke;
+ private final Set<CfInstructionDesugaring> precedingDesugaringsForInvokeDynamic;
/** Defines a minor variation in desugaring. */
public enum Flavor {
@@ -114,21 +113,29 @@
}
public static InterfaceMethodRewriter create(
- AppView<?> appView, Set<CfInstructionDesugaring> precedingDesugarings) {
+ AppView<?> appView,
+ Set<CfInstructionDesugaring> precedingDesugaringsForInvoke,
+ Set<CfInstructionDesugaring> precedingDesugaringsForInvokeDynamic) {
InterfaceMethodDesugaringMode desugaringMode =
getInterfaceMethodDesugaringMode(appView.options());
if (desugaringMode == NONE) {
return null;
}
- return new InterfaceMethodRewriter(appView, precedingDesugarings, desugaringMode);
+ return new InterfaceMethodRewriter(
+ appView,
+ precedingDesugaringsForInvoke,
+ precedingDesugaringsForInvokeDynamic,
+ desugaringMode);
}
- public InterfaceMethodRewriter(
+ private InterfaceMethodRewriter(
AppView<?> appView,
- Set<CfInstructionDesugaring> precedingDesugarings,
+ Set<CfInstructionDesugaring> precedingDesugaringsForInvoke,
+ Set<CfInstructionDesugaring> precedingDesugaringsForInvokeDynamic,
InterfaceMethodDesugaringMode desugaringMode) {
this.appView = appView;
- this.precedingDesugarings = precedingDesugarings;
+ this.precedingDesugaringsForInvoke = precedingDesugaringsForInvoke;
+ this.precedingDesugaringsForInvokeDynamic = precedingDesugaringsForInvokeDynamic;
this.options = appView.options();
this.factory = appView.dexItemFactory();
assert desugaringMode == EMULATED_INTERFACE_ONLY || desugaringMode == ALL;
@@ -197,7 +204,14 @@
private boolean isAlreadyDesugared(CfInvoke invoke, ProgramMethod context) {
return Iterables.any(
- precedingDesugarings, desugaring -> desugaring.compute(invoke, context).needsDesugaring());
+ precedingDesugaringsForInvoke,
+ desugaring -> desugaring.compute(invoke, context).needsDesugaring());
+ }
+
+ private boolean isAlreadyDesugared(CfInvokeDynamic invoke, ProgramMethod context) {
+ return Iterables.any(
+ precedingDesugaringsForInvokeDynamic,
+ desugaring -> desugaring.compute(invoke, context).needsDesugaring());
}
@Override
@@ -221,9 +235,7 @@
CfCode code = context.getDefinition().getCode().asCfCode();
for (CfInstruction instruction : code.getInstructions()) {
if (instruction.isInvokeDynamic()
- && !LambdaInstructionDesugaring.isLambdaInvoke(instruction, context, appView)
- && !StringConcatInstructionDesugaring.isStringConcatInvoke(
- instruction, appView.dexItemFactory())) {
+ && !isAlreadyDesugared(instruction.asInvokeDynamic(), context)) {
reportInterfaceMethodHandleCallSite(instruction.asInvokeDynamic().getCallSite(), context);
}
compute(instruction, context).scan();
@@ -940,7 +952,7 @@
// At this point we likely have a non-library type that may depend on default method information
// from its interfaces and the dependency should be reported.
if (implementing.isProgramClass() && !definedInterface.isLibraryClass()) {
- reportDependencyEdge(implementing.asProgramClass(), definedInterface, appView.appInfo());
+ appView.appInfo().reportDependencyEdge(implementing.asProgramClass(), definedInterface);
}
// Merge information from all superinterfaces.
@@ -974,31 +986,4 @@
MethodPosition position = new MethodPosition(method.asMethodReference());
options.warningMissingTypeForDesugar(origin, position, missing, method);
}
-
- public static void reportDependencyEdge(
- DexClass dependent, DexClass dependency, AppInfo appInfo) {
- assert !dependent.isLibraryClass();
- assert !dependency.isLibraryClass();
- DesugarGraphConsumer consumer = appInfo.app().options.desugarGraphConsumer;
- if (consumer != null) {
- Origin dependencyOrigin = dependency.getOrigin();
- java.util.Collection<DexType> dependents =
- appInfo.getSyntheticItems().getSynthesizingContextTypes(dependent.getType());
- if (dependents.isEmpty()) {
- reportDependencyEdge(consumer, dependencyOrigin, dependent);
- } else {
- for (DexType type : dependents) {
- reportDependencyEdge(consumer, dependencyOrigin, appInfo.definitionFor(type));
- }
- }
- }
- }
-
- private static void reportDependencyEdge(
- DesugarGraphConsumer consumer, Origin dependencyOrigin, DexClass clazz) {
- Origin dependentOrigin = clazz.getOrigin();
- if (dependentOrigin != dependencyOrigin) {
- consumer.accept(dependentOrigin, dependencyOrigin);
- }
- }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
index 19df173..c7e64b08 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.desugar.nest;
-import static com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter.reportDependencyEdge;
-
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.DexClass;
@@ -47,8 +45,8 @@
DexClass hostClass = nest.getHostClass();
for (DexClass memberClass : nest.getMembers()) {
if (hostClass.isProgramClass() || memberClass.isProgramClass()) {
- reportDependencyEdge(hostClass, memberClass, appView.appInfo());
- reportDependencyEdge(memberClass, hostClass, appView.appInfo());
+ appView.appInfo().reportDependencyEdge(hostClass, memberClass);
+ appView.appInfo().reportDependencyEdge(memberClass, hostClass);
}
}
},
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java
index 0b29d7e..ac70a25 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java
@@ -234,22 +234,6 @@
return builder.desugar(localStackAllocator);
}
- public static boolean isStringConcatInvoke(CfInstruction instruction, DexItemFactory factory) {
- CfInvokeDynamic invoke = instruction.asInvokeDynamic();
- if (invoke == null) {
- return false;
- }
- // We are interested in bootstrap methods StringConcatFactory::makeConcat
- // and StringConcatFactory::makeConcatWithConstants, both are static.
- DexCallSite callSite = invoke.getCallSite();
- if (callSite.bootstrapMethod.type.isInvokeStatic()) {
- DexMethod bootstrapMethod = callSite.bootstrapMethod.asMethod();
- return bootstrapMethod == factory.stringConcatFactoryMembers.makeConcat
- || bootstrapMethod == factory.stringConcatFactoryMembers.makeConcatWithConstants;
- }
- return false;
- }
-
private static String convertToString(DexValue value, ProgramMethod context) {
if (value.isDexValueString()) {
return value.asDexValueString().getValue().toString();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
index fb0c4d8..3792bd4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
@@ -276,6 +276,8 @@
sharedUtilityClassType, dexItemFactory.intArrayType, "$VALUES"))
.setAccessFlags(FieldAccessFlags.createPublicStaticFinalSynthetic())
.setApiLevel(appView.computedMinApiLevel())
+ .disableAndroidApiLevelCheckIf(
+ !appView.options().apiModelingOptions().isApiCallerIdentificationEnabled())
.build();
fieldAccessInfoCollectionModifierBuilder
.recordFieldReadInUnknownContext(valuesField.getReference())
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index cc88ca9..49f2fbb 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -47,6 +47,7 @@
import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AsmUtils;
+import com.android.tools.r8.utils.ClassFileConsumerDataImpl;
import com.android.tools.r8.utils.ComparatorUtils;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalGlobalSyntheticsProgramConsumer.InternalGlobalSyntheticsCfConsumer;
@@ -334,7 +335,10 @@
verifyCf(result);
}
ExceptionUtils.withConsumeResourceHandler(
- options.reporter, handler -> consumer.accept(ByteDataView.of(result), desc, handler));
+ options.reporter,
+ handler ->
+ consumer.acceptClassFile(
+ new ClassFileConsumerDataImpl(ByteDataView.of(result), desc, handler)));
}
private int compareTypesThroughLens(DexType a, DexType b) {
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 383c931..87af2b2 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -375,7 +375,8 @@
builder -> {
if (!targetDefinition.isAbstract()
&& targetDefinition.getApiLevelForCode().isNotSetApiLevel()) {
- assert target.isLibraryMethod();
+ assert target.isLibraryMethod()
+ || !appView.options().apiModelingOptions().enableLibraryApiModeling;
builder.setApiLevelForCode(
appView
.apiLevelCompute()
diff --git a/src/main/java/com/android/tools/r8/origin/GlobalSyntheticOrigin.java b/src/main/java/com/android/tools/r8/origin/GlobalSyntheticOrigin.java
new file mode 100644
index 0000000..cec0daf
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/origin/GlobalSyntheticOrigin.java
@@ -0,0 +1,23 @@
+// 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.origin;
+
+public class GlobalSyntheticOrigin extends Origin {
+
+ private static final Origin INSTANCE = new GlobalSyntheticOrigin(Origin.root());
+
+ public static Origin instance() {
+ return INSTANCE;
+ }
+
+ protected GlobalSyntheticOrigin(Origin parent) {
+ super(parent);
+ }
+
+ @Override
+ public String part() {
+ return "<synthetic>";
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileProviderUtils.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileProviderUtils.java
index bc3cbb5..e09b79c 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfileProviderUtils.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileProviderUtils.java
@@ -6,12 +6,23 @@
import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
+import com.android.tools.r8.TextInputStream;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.ClassReferenceUtils;
+import com.android.tools.r8.utils.MethodReferenceUtils;
import com.android.tools.r8.utils.UTF8TextInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
+import java.util.function.Consumer;
public class ArtProfileProviderUtils {
@@ -33,4 +44,101 @@
}
};
}
+
+ /** Serialize the given {@param artProfileProvider} to a string for writing it to a dump. */
+ public static String serializeToString(ArtProfileProvider artProfileProvider) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (OutputStreamWriter outputStreamWriter =
+ new OutputStreamWriter(baos, StandardCharsets.UTF_8)) {
+ artProfileProvider.getArtProfile(
+ new ArtProfileBuilder() {
+
+ @Override
+ public ArtProfileBuilder addClassRule(
+ Consumer<ArtProfileClassRuleBuilder> classRuleBuilderConsumer) {
+ classRuleBuilderConsumer.accept(
+ new ArtProfileClassRuleBuilder() {
+
+ @Override
+ public ArtProfileClassRuleBuilder setClassReference(
+ ClassReference classReference) {
+ writeLine(
+ outputStreamWriter, ClassReferenceUtils.toSmaliString(classReference));
+ return this;
+ }
+ });
+ return this;
+ }
+
+ @Override
+ public ArtProfileBuilder addMethodRule(
+ Consumer<ArtProfileMethodRuleBuilder> methodRuleBuilderConsumer) {
+ Box<MethodReference> methodReferenceBox = new Box<>();
+ methodRuleBuilderConsumer.accept(
+ new ArtProfileMethodRuleBuilder() {
+
+ @Override
+ public ArtProfileMethodRuleBuilder setMethodReference(
+ MethodReference methodReference) {
+ methodReferenceBox.set(methodReference);
+ return this;
+ }
+
+ @Override
+ public ArtProfileMethodRuleBuilder setMethodRuleInfo(
+ Consumer<ArtProfileMethodRuleInfoBuilder> methodRuleInfoBuilderConsumer) {
+ ArtProfileMethodRuleInfoImpl.Builder artProfileMethodRuleInfoBuilder =
+ ArtProfileMethodRuleInfoImpl.builder();
+ methodRuleInfoBuilderConsumer.accept(artProfileMethodRuleInfoBuilder);
+ ArtProfileMethodRuleInfoImpl artProfileMethodRuleInfo =
+ artProfileMethodRuleInfoBuilder.build();
+ try {
+ artProfileMethodRuleInfo.writeHumanReadableFlags(outputStreamWriter);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ return this;
+ }
+ });
+ writeLine(
+ outputStreamWriter, MethodReferenceUtils.toSmaliString(methodReferenceBox.get()));
+ return this;
+ }
+
+ @Override
+ public ArtProfileBuilder addHumanReadableArtProfile(
+ TextInputStream textInputStream,
+ Consumer<HumanReadableArtProfileParserBuilder> parserBuilderConsumer) {
+ try (InputStreamReader inputStreamReader =
+ new InputStreamReader(
+ textInputStream.getInputStream(), textInputStream.getCharset())) {
+ char[] buffer = new char[1024];
+ int len = inputStreamReader.read(buffer);
+ while (len != -1) {
+ outputStreamWriter.write(buffer, 0, len);
+ len = inputStreamReader.read(buffer);
+ }
+ writeLine(outputStreamWriter);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ return this;
+ }
+ });
+ }
+ return baos.toString();
+ }
+
+ private static void writeLine(OutputStreamWriter outputStreamWriter) {
+ writeLine(outputStreamWriter, "");
+ }
+
+ private static void writeLine(OutputStreamWriter outputStreamWriter, String string) {
+ try {
+ outputStreamWriter.write(string);
+ outputStreamWriter.write('\n');
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 7673d69..b46adc0 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -11,13 +11,12 @@
import static com.android.tools.r8.naming.IdentifierNameStringUtils.identifyIdentifier;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.isReflectionMethod;
import static com.android.tools.r8.shaking.KeepInfo.Joiner.asFieldJoinerOrNull;
+import static com.android.tools.r8.utils.CovariantReturnTypeUtils.modelLibraryMethodsWithCovariantReturnTypes;
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;
import static java.util.Collections.emptySet;
import com.android.tools.r8.Diagnostic;
-import com.android.tools.r8.androidapi.ComputedApiLevel;
-import com.android.tools.r8.androidapi.CovariantReturnTypeMethods;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
@@ -75,7 +74,6 @@
import com.android.tools.r8.graph.LookupMethodTarget;
import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.LookupTarget;
-import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodAccessInfoCollection;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.MethodResolutionResult.FailedResolutionResult;
@@ -3586,7 +3584,7 @@
if (mode.isInitialTreeShaking()) {
// Amend library methods with covariant return types.
timing.begin("Model library");
- modelLibraryMethodsWithCovariantReturnTypes();
+ modelLibraryMethodsWithCovariantReturnTypes(appView);
timing.end();
} else if (appView.getKeepInfo() != null) {
timing.begin("Retain keep info");
@@ -3645,30 +3643,6 @@
this::recordDependentMinimumKeepInfo);
}
- private void modelLibraryMethodsWithCovariantReturnTypes() {
- CovariantReturnTypeMethods.registerMethodsWithCovariantReturnType(
- appView.dexItemFactory(),
- method -> {
- DexLibraryClass libraryClass =
- DexLibraryClass.asLibraryClassOrNull(
- appView.appInfo().definitionForWithoutExistenceAssert(method.getHolderType()));
- if (libraryClass == null) {
- return;
- }
- // Check if the covariant method exists on the class.
- DexEncodedMethod covariantMethod = libraryClass.lookupMethod(method);
- if (covariantMethod != null) {
- return;
- }
- libraryClass.addVirtualMethod(
- DexEncodedMethod.builder()
- .setMethod(method)
- .setAccessFlags(MethodAccessFlags.builder().setPublic().build())
- .setApiLevelForDefinition(ComputedApiLevel.notSet())
- .build());
- });
- }
-
private void applyMinimumKeepInfo(DexProgramClass clazz) {
EnqueuerEvent preconditionEvent = UnconditionalKeepInfoEvent.get();
KeepClassInfo.Joiner minimumKeepInfoForClass =
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index 8c2a3bf..e92442b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.ProgramDefinition;
+import com.android.tools.r8.origin.GlobalSyntheticOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.MainDexInfo;
import java.util.Comparator;
@@ -55,7 +56,7 @@
static SynthesizingContext fromType(DexType type) {
// This method should only be used for synthesizing from a non-program context!
// Thus we have no origin info and place the context in the "base" feature.
- return new SynthesizingContext(type, type, Origin.unknown(), FeatureSplit.BASE);
+ return new SynthesizingContext(type, type, GlobalSyntheticOrigin.instance(), FeatureSplit.BASE);
}
static SynthesizingContext fromNonSyntheticInputContext(
@@ -96,6 +97,10 @@
this.featureSplit = featureSplit;
}
+ public boolean isSyntheticInputClass() {
+ return synthesizingContextType != inputContextType;
+ }
+
@Override
public int compareTo(SynthesizingContext other) {
return Comparator
@@ -103,6 +108,7 @@
// choose the context prefix for items.
.comparing(SynthesizingContext::getSynthesizingContextType)
// To ensure that equals coincides with compareTo == 0, we then compare 'type'.
+ // Also, the input type context is used as the hygienic prefix in intermediate modes.
.thenComparing(c -> c.inputContextType)
.compare(this, other);
}
@@ -111,6 +117,10 @@
return synthesizingContextType;
}
+ DexType getSynthesizingInputContext(boolean intermediate) {
+ return intermediate ? inputContextType : getSynthesizingContextType();
+ }
+
Origin getInputContextOrigin() {
return inputContextOrigin;
}
@@ -120,14 +130,14 @@
}
SynthesizingContext rewrite(NonIdentityGraphLens lens) {
- DexType rewrittenInputeContextType = lens.lookupType(inputContextType);
+ DexType rewrittenInputContextType = lens.lookupType(inputContextType);
DexType rewrittenSynthesizingContextType = lens.lookupType(synthesizingContextType);
- return rewrittenInputeContextType == inputContextType
+ return rewrittenInputContextType == inputContextType
&& rewrittenSynthesizingContextType == synthesizingContextType
? this
: new SynthesizingContext(
rewrittenSynthesizingContextType,
- rewrittenInputeContextType,
+ rewrittenInputContextType,
inputContextOrigin,
featureSplit);
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
index 097df5d..1a75811 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.synthesis;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
@@ -58,7 +59,13 @@
return context;
}
- final String getPrefixForExternalSyntheticType() {
+ final String getPrefixForExternalSyntheticType(AppView<?> appView) {
+ if (!appView.options().intermediate && context.isSyntheticInputClass() && !kind.isGlobal()) {
+ // If the input class was a synthetic and the build is non-intermediate, unwind the synthetic
+ // name back to the original context (if present in the textual type).
+ return SyntheticNaming.getOuterContextFromExternalSyntheticType(
+ getKind(), getHolder().getType());
+ }
return SyntheticNaming.getPrefixForExternalSyntheticType(getKind(), getHolder().getType());
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 8cf1e77..44f53b1 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -218,7 +218,7 @@
}
Result computeFinalSynthetics(AppView<?> appView, Timing timing) {
- assert verifyNoNestedSynthetics(appView.dexItemFactory());
+ assert verifyNoNestedSynthetics(appView);
assert verifyOneSyntheticPerSyntheticClass();
DexApplication application;
Builder lensBuilder = new Builder();
@@ -334,7 +334,7 @@
return !committed.containsType(type);
}
- private boolean verifyNoNestedSynthetics(DexItemFactory dexItemFactory) {
+ private boolean verifyNoNestedSynthetics(AppView<?> appView) {
// Check that the prefix of each synthetic is never itself synthetic.
committed.forEachItem(
item -> {
@@ -345,8 +345,12 @@
SyntheticNaming.getPrefixForExternalSyntheticType(item.getKind(), item.getHolder());
assert !prefix.contains(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
DexType context =
- dexItemFactory.createType(DescriptorUtils.getDescriptorFromClassBinaryName(prefix));
- assert isNotSyntheticType(context) || synthetics.isGlobalSyntheticClass(context);
+ appView
+ .dexItemFactory()
+ .createType(DescriptorUtils.getDescriptorFromClassBinaryName(prefix));
+ assert isNotSyntheticType(context)
+ || item.getContext().isSyntheticInputClass()
+ || synthetics.isGlobalSyntheticClass(context);
});
return true;
}
@@ -599,7 +603,7 @@
} else {
groupsPerPrefix
.computeIfAbsent(
- group.getRepresentative().getPrefixForExternalSyntheticType(),
+ group.getRepresentative().getPrefixForExternalSyntheticType(appView),
k -> new ArrayList<>())
.add(group);
}
@@ -615,7 +619,7 @@
EquivalenceGroup<T> group = groups.get(i);
assert group
.getRepresentative()
- .getPrefixForExternalSyntheticType()
+ .getPrefixForExternalSyntheticType(appView)
.equals(externalSyntheticTypePrefix);
// Two equivalence groups in same context type must be distinct otherwise the assignment
// of the synthetic name will be non-deterministic between the two.
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index 631231c..49746f4 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -37,8 +37,10 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.synthesis.SyntheticFinalization.Result;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
@@ -549,6 +551,33 @@
return syntheticContextsToSyntheticClasses;
}
+ public Collection<Origin> getSynthesizingOrigin(DexType type) {
+ if (!isSynthetic(type)) {
+ return Collections.emptyList();
+ }
+ ImmutableList.Builder<Origin> builder = ImmutableList.builder();
+ forEachSynthesizingContext(
+ type,
+ context -> {
+ builder.add(context.getInputContextOrigin());
+ });
+ return builder.build();
+ }
+
+ public DexType getSynthesizingInputContext(DexType syntheticType, InternalOptions options) {
+ if (!isSynthetic(syntheticType)) {
+ return null;
+ }
+ Box<DexType> uniqueInputContext = new Box<>(null);
+ forEachSynthesizingContext(
+ syntheticType,
+ context -> {
+ assert uniqueInputContext.get() == null;
+ uniqueInputContext.set(context.getSynthesizingInputContext(options.intermediate));
+ });
+ return uniqueInputContext.get();
+ }
+
public interface SynthesizingContextOracle {
Set<DexReference> getSynthesizingContexts(DexProgramClass clazz);
@@ -729,9 +758,7 @@
// This is to ensure a flat input-type -> synthetic-item mapping.
SynthesizingContext outerContext = getSynthesizingContext(context.getClassContext(), appView);
Function<SynthesizingContext, DexType> contextToType =
- c ->
- SyntheticNaming.createInternalType(
- kind, c, context.getSyntheticSuffix(), appView.dexItemFactory());
+ c -> SyntheticNaming.createInternalType(kind, c, context.getSyntheticSuffix(), appView);
return internalCreateProgramClass(
kind, fn, outerContext, contextToType.apply(outerContext), contextToType, appView);
}
@@ -1028,8 +1055,7 @@
SynthesizingContext outerContext = getSynthesizingContext(context, appView);
SyntheticKind kind = kindSelector.select(naming);
DexType type =
- SyntheticNaming.createInternalType(
- kind, outerContext, syntheticIdSupplier.get(), appView.dexItemFactory());
+ SyntheticNaming.createInternalType(kind, outerContext, syntheticIdSupplier.get(), appView);
SyntheticProgramClassBuilder classBuilder =
new SyntheticProgramClassBuilder(type, kind, outerContext, appView.dexItemFactory());
DexProgramClass clazz =
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
index aebc9ae..cf548f9 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
@@ -193,7 +193,7 @@
if (kind.isGlobal()) {
return type;
}
- String prefix = SyntheticNaming.getPrefixForExternalSyntheticType(kind, type);
+ String prefix = SyntheticNaming.getOuterContextFromExternalSyntheticType(kind, type);
return factory.createType(DescriptorUtils.getDescriptorFromClassBinaryName(prefix));
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 5c81e4d..95105f8 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.Version;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringForTesting;
@@ -419,6 +420,19 @@
return binaryName.substring(0, index);
}
+ static String getOuterContextFromExternalSyntheticType(SyntheticKind kind, DexType type) {
+ assert !kind.isGlobal();
+ String binaryName = type.toBinaryName();
+ int index =
+ binaryName.indexOf(
+ kind.isFixedSuffixSynthetic() ? kind.descriptor : EXTERNAL_SYNTHETIC_CLASS_SEPARATOR);
+ if (index < 0) {
+ throw new Unreachable(
+ "Unexpected failure to determine the context of synthetic class: " + binaryName);
+ }
+ return binaryName.substring(0, index);
+ }
+
static DexType createFixedType(
SyntheticKind kind, SynthesizingContext context, DexItemFactory factory) {
assert kind.isFixedSuffixSynthetic();
@@ -426,14 +440,14 @@
}
static DexType createInternalType(
- SyntheticKind kind, SynthesizingContext context, String id, DexItemFactory factory) {
+ SyntheticKind kind, SynthesizingContext context, String id, AppView<?> appView) {
assert !kind.isFixedSuffixSynthetic();
return createType(
INTERNAL_SYNTHETIC_CLASS_SEPARATOR,
kind,
- context.getSynthesizingContextType(),
+ context.getSynthesizingInputContext(appView.options().intermediate),
id,
- factory);
+ appView.dexItemFactory());
}
static DexType createExternalType(
diff --git a/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java b/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
index 416a9a4..e1000f6 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.tracereferences;
+import static com.android.tools.r8.utils.CovariantReturnTypeUtils.modelLibraryMethodsWithCovariantReturnTypes;
+
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.Keep;
import com.android.tools.r8.ProgramResource;
@@ -11,8 +13,14 @@
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.Version;
import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.experimental.startup.StartupOrder;
+import com.android.tools.r8.features.ClassToFeatureSplitMap;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.origin.CommandLineOrigin;
+import com.android.tools.r8.shaking.MainDexInfo;
+import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -73,7 +81,20 @@
for (ProgramResourceProvider provider : command.getSource()) {
forEachDescriptor(provider, targetDescriptors::remove);
}
- Tracer tracer = new Tracer(targetDescriptors, builder.build(), command.getReporter(), options);
+ AppView<AppInfoWithClassHierarchy> appView =
+ AppView.createForTracer(
+ AppInfoWithClassHierarchy.createInitialAppInfoWithClassHierarchy(
+ new ApplicationReader(builder.build(), options, Timing.empty()).read().toDirect(),
+ ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap(),
+ MainDexInfo.none(),
+ GlobalSyntheticsStrategy.forSingleOutputMode(),
+ StartupOrder.empty()));
+ modelLibraryMethodsWithCovariantReturnTypes(appView);
+ Tracer tracer =
+ new Tracer(
+ appView,
+ command.getReporter(),
+ type -> targetDescriptors.contains(type.toDescriptorString()));
tracer.run(command.getConsumer());
}
diff --git a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
index 97c4499..f182a0b 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
@@ -4,11 +4,8 @@
package com.android.tools.r8.tracereferences;
import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.diagnostic.DefinitionContext;
import com.android.tools.r8.diagnostic.internal.DefinitionContextUtils;
-import com.android.tools.r8.experimental.startup.StartupOrder;
-import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassResolutionResult;
@@ -41,17 +38,11 @@
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.shaking.MainDexInfo;
-import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
import com.android.tools.r8.tracereferences.TraceReferencesConsumer.TracedReference;
import com.android.tools.r8.tracereferences.internal.TracedClassImpl;
import com.android.tools.r8.tracereferences.internal.TracedFieldImpl;
import com.android.tools.r8.tracereferences.internal.TracedMethodImpl;
-import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BooleanBox;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Timing;
-import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
@@ -63,24 +54,6 @@
private final DiagnosticsHandler diagnostics;
private final Predicate<DexType> targetPredicate;
- Tracer(
- Set<String> targetDescriptors,
- AndroidApp inputApp,
- DiagnosticsHandler diagnostics,
- InternalOptions options)
- throws IOException {
- this(
- AppView.createForTracer(
- AppInfoWithClassHierarchy.createInitialAppInfoWithClassHierarchy(
- new ApplicationReader(inputApp, options, Timing.empty()).read().toDirect(),
- ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap(),
- MainDexInfo.none(),
- GlobalSyntheticsStrategy.forSingleOutputMode(),
- StartupOrder.empty())),
- diagnostics,
- type -> targetDescriptors.contains(type.toDescriptorString()));
- }
-
public Tracer(
AppView<? extends AppInfoWithClassHierarchy> appView,
DiagnosticsHandler diagnostics,
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index 2e7e2e3..fd21f2a 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -47,12 +47,13 @@
MASTER(35), // API level for master is tentative.
ANDROID_PLATFORM(10000);
- // When updating LATEST and a new version goes stable, add a new api-versions.xml to third_party
- // and update the version and generated jar in AndroidApiDatabaseBuilderGeneratorTest.
- public static final AndroidApiLevel LATEST = T;
+ // When updating LATEST and a new version goes public, add a new api-versions.xml to third_party
+ // and update the version and generated jar in AndroidApiDatabaseBuilderGeneratorTest. Together
+ // with that update third_party/android_jar/libcore_latest/core-oj.jar and run
+ // GenerateCovariantReturnTypeMethodsTest.
+ public static final AndroidApiLevel LATEST = U;
- // TODO(b/268601605): When adding U to the test matrix, set this to LATEST.
- public static final AndroidApiLevel API_DATABASE_LEVEL = U;
+ public static final AndroidApiLevel API_DATABASE_LEVEL = LATEST;
private final int level;
@@ -109,7 +110,7 @@
public static AndroidApiLevel getAndroidApiLevel(int apiLevel) {
assert apiLevel > 0;
- assert T == LATEST; // This has to be updated when we add new api levels.
+ assert U == LATEST; // This has to be updated when we add new api levels.
assert ANDROID_PLATFORM.isGreaterThan(LATEST);
switch (apiLevel) {
case 1:
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 8ea5c72..cf3047d 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -42,6 +42,8 @@
import com.android.tools.r8.origin.ArchiveEntryOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.profile.art.ArtProfileProvider;
+import com.android.tools.r8.profile.art.ArtProfileProviderUtils;
import com.android.tools.r8.shaking.FilteredClassPath;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.synthesis.SyntheticItems;
@@ -539,6 +541,9 @@
StringUtils.joinLines(dumpOptions.getMainDexKeepRules()).getBytes(),
ZipEntry.DEFLATED);
}
+ if (dumpOptions.hasArtProfileProviders()) {
+ dumpArtProfileProviders(dumpOptions.getArtProfileProviders(), options, out);
+ }
if (dumpOptions.hasStartupProfileProviders()) {
dumpStartupProfileProviders(dumpOptions.getStartupProfileProviders(), options, out);
}
@@ -571,6 +576,23 @@
return nextDexIndex;
}
+ private void dumpArtProfileProviders(
+ Collection<ArtProfileProvider> artProfileProviders,
+ InternalOptions options,
+ ZipOutputStream out)
+ throws IOException {
+ int artProfileProviderIndex = 1;
+ for (ArtProfileProvider artProfileProvider : artProfileProviders) {
+ String artProfileFileName = "art-profile-" + artProfileProviderIndex + ".txt";
+ writeToZipStream(
+ out,
+ artProfileFileName,
+ ArtProfileProviderUtils.serializeToString(artProfileProvider).getBytes(),
+ ZipEntry.DEFLATED);
+ artProfileProviderIndex++;
+ }
+ }
+
private void dumpStartupProfileProviders(
Collection<StartupProfileProvider> startupProfileProviders,
InternalOptions options,
@@ -578,11 +600,10 @@
throws IOException {
int startupProfileProviderIndex = 1;
for (StartupProfileProvider startupProfileProvider : startupProfileProviders) {
- String startupProfileProviderFileName =
- "startup-profile-" + startupProfileProviderIndex + ".txt";
+ String startupProfileFileName = "startup-profile-" + startupProfileProviderIndex + ".txt";
writeToZipStream(
out,
- startupProfileProviderFileName,
+ startupProfileFileName,
StartupProfileProviderUtils.serializeToString(options, startupProfileProvider).getBytes(),
ZipEntry.DEFLATED);
startupProfileProviderIndex++;
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
index 7a77e25..1c01a7b 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
@@ -4,14 +4,16 @@
package com.android.tools.r8.utils;
import com.android.tools.r8.BaseCompilerCommand;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.ClassFileConsumerData;
import com.android.tools.r8.DataDirectoryResource;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceConsumer;
import com.android.tools.r8.DexFilePerClassFileConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DexIndexedConsumer.ForwardingConsumer;
+import com.android.tools.r8.DexIndexedConsumerData;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.ResourceException;
@@ -103,13 +105,9 @@
new Int2ReferenceAVLTreeMap<>();
@Override
- public void accept(
- int fileIndex,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- super.accept(fileIndex, data, descriptors, handler);
- addDexFile(fileIndex, data.copyByteData(), descriptors);
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ super.acceptDexIndexedFile(data);
+ addDexFile(data.getFileIndex(), data.getByteDataCopy(), data.getClassDescriptors());
}
@Override
@@ -182,13 +180,12 @@
private TreeMap<String, DescriptorsWithContents> files = new TreeMap<>();
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- super.accept(primaryClassDescriptor, data, descriptors, handler);
- addDexFile(primaryClassDescriptor, data.copyByteData(), descriptors);
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ super.acceptDexFile(data);
+ addDexFile(
+ data.getPrimaryClassDescriptor(),
+ data.getByteDataCopy(),
+ data.getClassDescriptors());
}
synchronized void addDexFile(
@@ -258,9 +255,9 @@
private List<DescriptorsWithContents> files = new ArrayList<>();
@Override
- public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
- super.accept(data, descriptor, handler);
- addClassFile(data.copyByteData(), descriptor);
+ public void acceptClassFile(ClassFileConsumerData data) {
+ super.acceptClassFile(data);
+ addClassFile(data.getByteDataCopy(), data.getClassDescriptor());
}
synchronized void addClassFile(byte[] data, String descriptor) {
diff --git a/src/main/java/com/android/tools/r8/utils/ClassFileConsumerDataImpl.java b/src/main/java/com/android/tools/r8/utils/ClassFileConsumerDataImpl.java
new file mode 100644
index 0000000..b375086
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/ClassFileConsumerDataImpl.java
@@ -0,0 +1,43 @@
+// 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.utils;
+
+import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.ClassFileConsumerData;
+import com.android.tools.r8.DiagnosticsHandler;
+
+/** Internal implementation of the consumer data. */
+public class ClassFileConsumerDataImpl implements ClassFileConsumerData {
+
+ private final ByteDataView data;
+ private final String descriptor;
+ private final DiagnosticsHandler handler;
+
+ public ClassFileConsumerDataImpl(
+ ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ this.data = data;
+ this.descriptor = descriptor;
+ this.handler = handler;
+ }
+
+ @Override
+ public ByteDataView getByteDataView() {
+ return data;
+ }
+
+ @Override
+ public byte[] getByteDataCopy() {
+ return data.copyByteData();
+ }
+
+ @Override
+ public String getClassDescriptor() {
+ return descriptor;
+ }
+
+ @Override
+ public DiagnosticsHandler getDiagnosticsHandler() {
+ return handler;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java b/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java
new file mode 100644
index 0000000..2a928b0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java
@@ -0,0 +1,171 @@
+// 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.utils;
+
+import com.android.tools.r8.CompatProguardCommandBuilder;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public class CompileDumpBase {
+
+ static void setEnableExperimentalMissingLibraryApiModeling(
+ Object builder, boolean enableMissingLibraryApiModeling) {
+ getReflectiveBuilderMethod(
+ builder, "setEnableExperimentalMissingLibraryApiModeling", boolean.class)
+ .accept(new Object[] {enableMissingLibraryApiModeling});
+ }
+
+ static void setAndroidPlatformBuild(Object builder, boolean androidPlatformBuild) {
+ getReflectiveBuilderMethod(builder, "setAndroidPlatformBuild", boolean.class)
+ .accept(new Object[] {androidPlatformBuild});
+ }
+
+ static void addArtProfilesForRewriting(Object builder, Map<Path, Path> artProfileFiles) {
+ try {
+ Class<?> artProfileProviderClass =
+ Class.forName("com.android.tools.r8.profile.art.ArtProfileProvider");
+ Class<?> artProfileConsumerClass =
+ Class.forName("com.android.tools.r8.profile.art.ArtProfileConsumer");
+ artProfileFiles.forEach(
+ (artProfile, residualArtProfile) ->
+ getReflectiveBuilderMethod(
+ builder,
+ "addArtProfileForRewriting",
+ artProfileProviderClass,
+ artProfileConsumerClass)
+ .accept(
+ new Object[] {
+ createArtProfileProvider(artProfile),
+ createResidualArtProfileConsumer(residualArtProfile)
+ }));
+ } catch (ClassNotFoundException e) {
+ // Ignore.
+ }
+ }
+
+ static void addStartupProfileProviders(Object builder, List<Path> startupProfileFiles) {
+ getReflectiveBuilderMethod(builder, "addStartupProfileProviders", Collection.class)
+ .accept(new Object[] {createStartupProfileProviders(startupProfileFiles)});
+ }
+
+ static Object createArtProfileProvider(Path artProfile) {
+ Object[] artProfileProvider = new Object[1];
+ boolean found =
+ callReflectiveUtilsMethod(
+ "createArtProfileProviderFromDumpFile",
+ new Class<?>[] {Path.class},
+ fn -> artProfileProvider[0] = fn.apply(new Object[] {artProfile}));
+ if (!found) {
+ System.out.println(
+ "Unable to add art profiles as input. "
+ + "Method createArtProfileProviderFromDumpFile() was not found.");
+ return null;
+ }
+ System.out.println(artProfileProvider[0]);
+ return artProfileProvider[0];
+ }
+
+ static Object createResidualArtProfileConsumer(Path residualArtProfile) {
+ Object[] residualArtProfileConsumer = new Object[1];
+ boolean found =
+ callReflectiveUtilsMethod(
+ "createResidualArtProfileConsumerFromDumpFile",
+ new Class<?>[] {Path.class},
+ fn -> residualArtProfileConsumer[0] = fn.apply(new Object[] {residualArtProfile}));
+ if (!found) {
+ System.out.println(
+ "Unable to add art profiles as input. "
+ + "Method createResidualArtProfileConsumerFromDumpFile() was not found.");
+ return null;
+ }
+ System.out.println(residualArtProfileConsumer[0]);
+ return residualArtProfileConsumer[0];
+ }
+
+ static Collection<Object> createStartupProfileProviders(List<Path> startupProfileFiles) {
+ List<Object> startupProfileProviders = new ArrayList<>();
+ for (Path startupProfileFile : startupProfileFiles) {
+ boolean found =
+ callReflectiveUtilsMethod(
+ "createStartupProfileProviderFromDumpFile",
+ new Class<?>[] {Path.class},
+ fn -> startupProfileProviders.add(fn.apply(new Object[] {startupProfileFile})));
+ if (!found) {
+ System.out.println(
+ "Unable to add startup profiles as input. "
+ + "Method createStartupProfileProviderFromDumpFile() was not found.");
+ break;
+ }
+ }
+ return startupProfileProviders;
+ }
+
+ static Consumer<Object[]> getReflectiveBuilderMethod(
+ Object builder, String setter, Class<?>... parameters) {
+ try {
+ Method declaredMethod = CompatProguardCommandBuilder.class.getMethod(setter, parameters);
+ return args -> {
+ try {
+ declaredMethod.invoke(builder, args);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ };
+ } catch (NoSuchMethodException e) {
+ System.out.println(setter + " is not available on the compiledump version.");
+ // The option is not available so we just return an empty consumer
+ return args -> {};
+ }
+ }
+
+ static boolean callReflectiveUtilsMethod(
+ String methodName, Class<?>[] parameters, Consumer<Function<Object[], Object>> fnConsumer) {
+ Class<?> utilsClass;
+ try {
+ utilsClass = Class.forName("com.android.tools.r8.utils.CompileDumpUtils");
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+
+ Method declaredMethod;
+ try {
+ declaredMethod = utilsClass.getDeclaredMethod(methodName, parameters);
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+
+ fnConsumer.accept(
+ args -> {
+ try {
+ return declaredMethod.invoke(null, args);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ return true;
+ }
+
+ // We cannot use StringResource since this class is added to the class path and has access only
+ // to the public APIs.
+ static String readAllBytesJava7(Path filePath) {
+ String content = "";
+
+ try {
+ content = new String(Files.readAllBytes(filePath));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return content;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
index 57cdc5f..c4612a7 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
@@ -12,21 +12,15 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.StringConsumer;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.function.Consumer;
-import java.util.function.Function;
/**
* Wrapper to make it easy to call R8 in compat mode when compiling a dump file.
@@ -38,7 +32,7 @@
* valid on past version of the R8 API. Thus there is little else to do than reimplement the parts
* we want to support for reading dumps.
*/
-public class CompileDumpCompatR8 {
+public class CompileDumpCompatR8 extends CompileDumpBase {
private static final List<String> VALID_OPTIONS =
Arrays.asList(
@@ -66,7 +60,7 @@
"--startup-profile");
private static final List<String> VALID_OPTIONS_WITH_TWO_OPERANDS =
- Arrays.asList("--feature-jar");
+ Arrays.asList("--art-profile", "--feature-jar");
private static boolean FileUtils_isArchive(Path path) {
String name = path.getFileName().toString().toLowerCase();
@@ -90,6 +84,7 @@
List<Path> classpath = new ArrayList<>();
List<Path> config = new ArrayList<>();
List<Path> mainDexRulesFiles = new ArrayList<>();
+ Map<Path, Path> artProfileFiles = new LinkedHashMap<>();
List<Path> startupProfileFiles = new ArrayList<>();
int minApi = 1;
int threads = -1;
@@ -193,6 +188,11 @@
String firstOperand = args[++i];
String secondOperand = args[++i];
switch (option) {
+ case "--art-profile":
+ {
+ artProfileFiles.put(Paths.get(firstOperand), Paths.get(secondOperand));
+ break;
+ }
case "--feature-jar":
{
Path featureIn = Paths.get(firstOperand);
@@ -220,13 +220,10 @@
.addMainDexRulesFiles(mainDexRulesFiles)
.setOutput(outputPath, outputMode)
.setMode(compilationMode);
- getReflectiveBuilderMethod(
- commandBuilder, "setEnableExperimentalMissingLibraryApiModeling", boolean.class)
- .accept(new Object[] {enableMissingLibraryApiModeling});
- getReflectiveBuilderMethod(commandBuilder, "setAndroidPlatformBuild", boolean.class)
- .accept(new Object[] {androidPlatformBuild});
- getReflectiveBuilderMethod(commandBuilder, "addStartupProfileProviders", Collection.class)
- .accept(new Object[] {createStartupProfileProviders(startupProfileFiles)});
+ addArtProfilesForRewriting(commandBuilder, artProfileFiles);
+ addStartupProfileProviders(commandBuilder, startupProfileFiles);
+ setAndroidPlatformBuild(commandBuilder, androidPlatformBuild);
+ setEnableExperimentalMissingLibraryApiModeling(commandBuilder, enableMissingLibraryApiModeling);
if (desugaredLibJson != null) {
commandBuilder.addDesugaredLibraryConfiguration(readAllBytesJava7(desugaredLibJson));
}
@@ -259,81 +256,4 @@
R8.run(command);
}
}
-
- private static Collection<Object> createStartupProfileProviders(List<Path> startupProfileFiles) {
- List<Object> startupProfileProviders = new ArrayList<>();
- for (Path startupProfileFile : startupProfileFiles) {
- boolean found =
- callReflectiveUtilsMethod(
- "createStartupProfileProviderFromDumpFile",
- new Class<?>[] {Path.class},
- fn -> startupProfileProviders.add(fn.apply(new Object[] {startupProfileFile})));
- if (!found) {
- System.out.println(
- "Unable to add startup profiles as input. "
- + "Method createStartupProfileProviderFromDumpFile() was not found.");
- break;
- }
- }
- return startupProfileProviders;
- }
-
- private static Consumer<Object[]> getReflectiveBuilderMethod(
- Builder builder, String setter, Class<?>... parameters) {
- try {
- Method declaredMethod = CompatProguardCommandBuilder.class.getMethod(setter, parameters);
- return args -> {
- try {
- declaredMethod.invoke(builder, args);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- };
- } catch (NoSuchMethodException e) {
- System.out.println(setter + " is not available on the compiledump version.");
- // The option is not available so we just return an empty consumer
- return args -> {};
- }
- }
-
- private static boolean callReflectiveUtilsMethod(
- String methodName, Class<?>[] parameters, Consumer<Function<Object[], Object>> fnConsumer) {
- Class<?> utilsClass;
- try {
- utilsClass = Class.forName("com.android.tools.r8.utils.CompileDumpUtils");
- } catch (ClassNotFoundException e) {
- return false;
- }
-
- Method declaredMethod;
- try {
- declaredMethod = utilsClass.getMethod(methodName, parameters);
- } catch (NoSuchMethodException e) {
- return false;
- }
-
- fnConsumer.accept(
- args -> {
- try {
- return declaredMethod.invoke(null, args);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
- return true;
- }
-
- // We cannot use StringResource since this class is added to the class path and has access only
- // to the public APIs.
- private static String readAllBytesJava7(Path filePath) {
- String content = "";
-
- try {
- content = new String(Files.readAllBytes(filePath));
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- return content;
- }
}
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpD8.java b/src/main/java/com/android/tools/r8/utils/CompileDumpD8.java
index 613701c..b63f5d8 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpD8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpD8.java
@@ -8,19 +8,15 @@
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.OutputMode;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.function.Consumer;
-import java.util.function.Function;
/**
* Wrapper to make it easy to call D8 mode when compiling a dump file.
@@ -32,7 +28,7 @@
* valid on past version of the D8 API. Thus there is little else to do than reimplement the parts
* we want to support for reading dumps.
*/
-public class CompileDumpD8 {
+public class CompileDumpD8 extends CompileDumpBase {
private static final List<String> VALID_OPTIONS =
Arrays.asList(
@@ -55,6 +51,9 @@
"--threads",
"--startup-profile");
+ private static final List<String> VALID_OPTIONS_WITH_TWO_OPERANDS =
+ Arrays.asList("--art-profile");
+
public static void main(String[] args) throws CompilationFailedException {
OutputMode outputMode = OutputMode.DexIndexed;
Path outputPath = null;
@@ -64,6 +63,7 @@
List<Path> library = new ArrayList<>();
List<Path> classpath = new ArrayList<>();
List<Path> mainDexRulesFiles = new ArrayList<>();
+ Map<Path, Path> artProfileFiles = new LinkedHashMap<>();
List<Path> startupProfileFiles = new ArrayList<>();
int minApi = 1;
int threads = -1;
@@ -143,6 +143,18 @@
default:
throw new IllegalArgumentException("Unimplemented option: " + option);
}
+ } else if (VALID_OPTIONS_WITH_TWO_OPERANDS.contains(option)) {
+ String firstOperand = args[++i];
+ String secondOperand = args[++i];
+ switch (option) {
+ case "--art-profile":
+ {
+ artProfileFiles.put(Paths.get(firstOperand), Paths.get(secondOperand));
+ break;
+ }
+ default:
+ throw new IllegalArgumentException("Unimplemented option: " + option);
+ }
} else {
program.add(Paths.get(option));
}
@@ -155,13 +167,10 @@
.addMainDexRulesFiles(mainDexRulesFiles)
.setOutput(outputPath, outputMode)
.setMode(compilationMode);
- getReflectiveBuilderMethod(
- commandBuilder, "setEnableExperimentalMissingLibraryApiModeling", boolean.class)
- .accept(new Object[] {enableMissingLibraryApiModeling});
- getReflectiveBuilderMethod(commandBuilder, "setAndroidPlatformBuild", boolean.class)
- .accept(new Object[] {androidPlatformBuild});
- getReflectiveBuilderMethod(commandBuilder, "addStartupProfileProviders", Collection.class)
- .accept(new Object[] {createStartupProfileProviders(startupProfileFiles)});
+ addArtProfilesForRewriting(commandBuilder, artProfileFiles);
+ addStartupProfileProviders(commandBuilder, startupProfileFiles);
+ setAndroidPlatformBuild(commandBuilder, androidPlatformBuild);
+ setEnableExperimentalMissingLibraryApiModeling(commandBuilder, enableMissingLibraryApiModeling);
if (desugaredLibJson != null) {
commandBuilder.addDesugaredLibraryConfiguration(readAllBytesJava7(desugaredLibJson));
}
@@ -178,81 +187,4 @@
D8.run(command);
}
}
-
- private static Collection<Object> createStartupProfileProviders(List<Path> startupProfileFiles) {
- List<Object> startupProfileProviders = new ArrayList<>();
- for (Path startupProfileFile : startupProfileFiles) {
- boolean found =
- callReflectiveUtilsMethod(
- "createStartupProfileProviderFromDumpFile",
- new Class<?>[] {Path.class},
- fn -> startupProfileProviders.add(fn.apply(new Object[] {startupProfileFile})));
- if (!found) {
- System.out.println(
- "Unable to add startup profiles as input. "
- + "Method createStartupProfileProviderFromDumpFile() was not found.");
- break;
- }
- }
- return startupProfileProviders;
- }
-
- private static Consumer<Object[]> getReflectiveBuilderMethod(
- D8Command.Builder builder, String setter, Class<?>... parameters) {
- try {
- Method declaredMethod = D8Command.Builder.class.getMethod(setter, parameters);
- return args -> {
- try {
- declaredMethod.invoke(builder, args);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- };
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- // The option is not available so we just return an empty consumer
- return args -> {};
- }
- }
-
- private static boolean callReflectiveUtilsMethod(
- String methodName, Class<?>[] parameters, Consumer<Function<Object[], Object>> fnConsumer) {
- Class<?> utilsClass;
- try {
- utilsClass = Class.forName("com.android.tools.r8.utils.CompileDumpUtils");
- } catch (ClassNotFoundException e) {
- return false;
- }
-
- Method declaredMethod;
- try {
- declaredMethod = utilsClass.getMethod(methodName, parameters);
- } catch (NoSuchMethodException e) {
- return false;
- }
-
- fnConsumer.accept(
- args -> {
- try {
- return declaredMethod.invoke(null, args);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
- return true;
- }
-
- // We cannot use StringResource since this class is added to the class path and has access only
- // to the public APIs.
- private static String readAllBytesJava7(Path filePath) {
- String content = "";
-
- try {
- content = new String(Files.readAllBytes(filePath));
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- return content;
- }
}
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpUtils.java b/src/main/java/com/android/tools/r8/utils/CompileDumpUtils.java
index 14acc11..f0275f5 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpUtils.java
@@ -7,6 +7,10 @@
import com.android.tools.r8.KeepMethodForCompileDump;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.profile.art.ArtProfileConsumer;
+import com.android.tools.r8.profile.art.ArtProfileConsumerUtils;
+import com.android.tools.r8.profile.art.ArtProfileProvider;
+import com.android.tools.r8.profile.art.ArtProfileProviderUtils;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.startup.StartupProfileBuilder;
@@ -20,6 +24,16 @@
class CompileDumpUtils {
@KeepMethodForCompileDump
+ static ArtProfileProvider createArtProfileProviderFromDumpFile(Path artProfile) {
+ return ArtProfileProviderUtils.createFromHumanReadableArtProfile(artProfile);
+ }
+
+ @KeepMethodForCompileDump
+ static ArtProfileConsumer createResidualArtProfileConsumerFromDumpFile(Path residualArtProfile) {
+ return ArtProfileConsumerUtils.create(residualArtProfile);
+ }
+
+ @KeepMethodForCompileDump
static StartupProfileProvider createStartupProfileProviderFromDumpFile(Path path) {
return new StartupProfileProvider() {
diff --git a/src/main/java/com/android/tools/r8/utils/CovariantReturnTypeUtils.java b/src/main/java/com/android/tools/r8/utils/CovariantReturnTypeUtils.java
new file mode 100644
index 0000000..202132f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/CovariantReturnTypeUtils.java
@@ -0,0 +1,39 @@
+// 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.utils;
+
+import com.android.tools.r8.androidapi.ComputedApiLevel;
+import com.android.tools.r8.androidapi.CovariantReturnTypeMethods;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexLibraryClass;
+import com.android.tools.r8.graph.MethodAccessFlags;
+
+public class CovariantReturnTypeUtils {
+
+ public static void modelLibraryMethodsWithCovariantReturnTypes(AppView<?> appView) {
+ CovariantReturnTypeMethods.registerMethodsWithCovariantReturnType(
+ appView.dexItemFactory(),
+ method -> {
+ DexLibraryClass libraryClass =
+ DexLibraryClass.asLibraryClassOrNull(
+ appView.appInfo().definitionForWithoutExistenceAssert(method.getHolderType()));
+ if (libraryClass == null) {
+ return;
+ }
+ // Check if the covariant method exists on the class.
+ DexEncodedMethod covariantMethod = libraryClass.lookupMethod(method);
+ if (covariantMethod != null) {
+ return;
+ }
+ libraryClass.addVirtualMethod(
+ DexEncodedMethod.builder()
+ .setMethod(method)
+ .setAccessFlags(MethodAccessFlags.builder().setPublic().build())
+ .setApiLevelForDefinition(ComputedApiLevel.notSet())
+ .build());
+ });
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java b/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java
new file mode 100644
index 0000000..9dc9e8b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java
@@ -0,0 +1,61 @@
+// 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.utils;
+
+import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
+import com.android.tools.r8.DiagnosticsHandler;
+import java.util.Set;
+
+public class DexFilePerClassFileConsumerDataImpl implements DexFilePerClassFileConsumerData {
+
+ private final String primaryClassDescriptor;
+ private final String synthesizingContextDescriptor;
+ private final ByteDataView data;
+ private final Set<String> classDescriptors;
+ private final DiagnosticsHandler handler;
+
+ public DexFilePerClassFileConsumerDataImpl(
+ String primaryClassDescriptor,
+ String synthesizingContextDescriptor,
+ ByteDataView data,
+ Set<String> classDescriptors,
+ DiagnosticsHandler handler) {
+ this.primaryClassDescriptor = primaryClassDescriptor;
+ this.synthesizingContextDescriptor = synthesizingContextDescriptor;
+ this.data = data;
+ this.classDescriptors = classDescriptors;
+ this.handler = handler;
+ }
+
+ @Override
+ public String getPrimaryClassDescriptor() {
+ return primaryClassDescriptor;
+ }
+
+ @Override
+ public String getSynthesizingContextForPrimaryClass() {
+ return synthesizingContextDescriptor;
+ }
+
+ @Override
+ public ByteDataView getByteDataView() {
+ return data;
+ }
+
+ @Override
+ public byte[] getByteDataCopy() {
+ return data.copyByteData();
+ }
+
+ @Override
+ public Set<String> getClassDescriptors() {
+ return classDescriptors;
+ }
+
+ @Override
+ public DiagnosticsHandler getDiagnosticsHandler() {
+ return handler;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/DexIndexedConsumerDataImpl.java b/src/main/java/com/android/tools/r8/utils/DexIndexedConsumerDataImpl.java
new file mode 100644
index 0000000..2de21e4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/DexIndexedConsumerDataImpl.java
@@ -0,0 +1,50 @@
+// 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.utils;
+
+import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.DexIndexedConsumerData;
+import com.android.tools.r8.DiagnosticsHandler;
+import java.util.Set;
+
+public class DexIndexedConsumerDataImpl implements DexIndexedConsumerData {
+
+ private final int fileIndex;
+ private final ByteDataView data;
+ private final Set<String> classDescriptors;
+ private final DiagnosticsHandler handler;
+
+ public DexIndexedConsumerDataImpl(
+ int fileIndex, ByteDataView data, Set<String> classDescriptors, DiagnosticsHandler handler) {
+ this.fileIndex = fileIndex;
+ this.data = data;
+ this.classDescriptors = classDescriptors;
+ this.handler = handler;
+ }
+
+ @Override
+ public int getFileIndex() {
+ return fileIndex;
+ }
+
+ @Override
+ public ByteDataView getByteDataView() {
+ return data;
+ }
+
+ @Override
+ public byte[] getByteDataCopy() {
+ return data.copyByteData();
+ }
+
+ @Override
+ public Set<String> getClassDescriptors() {
+ return classDescriptors;
+ }
+
+ @Override
+ public DiagnosticsHandler getDiagnosticsHandler() {
+ return handler;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java b/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java
index 1428459..6fcc519 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.DexFilePerClassFileConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.GlobalSyntheticsConsumer;
import com.android.tools.r8.ProgramConsumer;
@@ -102,12 +103,8 @@
}
@Override
- public synchronized void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- builder.addGlobalSynthetic(primaryClassDescriptor, data.copyByteData());
+ public synchronized void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ builder.addGlobalSynthetic(data.getPrimaryClassDescriptor(), data.getByteDataCopy());
}
@Override
@@ -149,12 +146,8 @@
}
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- addGlobal(primaryClassDescriptor, data);
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ addGlobal(data.getPrimaryClassDescriptor(), data.getByteDataView());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index f7c00ee..b26527a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2850,14 +2850,15 @@
// the symbolic reference java.lang.Object.
//
// The support was added in Android O, however at least for j.l.CharSequence.equals the handling
- // in Art was incorrect (b/231450655).
+ // in Art was incorrect (b/231450655). Further down the line b/271408544 indicate that it is not
+ // until Android S that this is working.
//
// javac started generating code like this with the fix for JDK-8272564, which will be part of
// JDK 18.
//
// See b/218298666.
public boolean canHaveInvokeInterfaceToObjectMethodBug() {
- return canHaveBugPresentUntil(AndroidApiLevel.P);
+ return canHaveBugPresentUntil(AndroidApiLevel.S);
}
// Until we fully drop support for API levels < 16, we have to emit an empty annotation set to
diff --git a/src/main/java/com/android/tools/r8/utils/UTF8TextInputStream.java b/src/main/java/com/android/tools/r8/utils/UTF8TextInputStream.java
index 20252e7..709df16 100644
--- a/src/main/java/com/android/tools/r8/utils/UTF8TextInputStream.java
+++ b/src/main/java/com/android/tools/r8/utils/UTF8TextInputStream.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.utils;
import com.android.tools.r8.TextInputStream;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
@@ -20,6 +21,10 @@
this(Files.newInputStream(path));
}
+ public UTF8TextInputStream(String string) {
+ this(new ByteArrayInputStream(string.getBytes()));
+ }
+
public UTF8TextInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
diff --git a/src/test/examplesJava17/records/RecordInterface.java b/src/test/examplesJava17/records/RecordInterface.java
new file mode 100644
index 0000000..8fc1e56
--- /dev/null
+++ b/src/test/examplesJava17/records/RecordInterface.java
@@ -0,0 +1,21 @@
+// 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 records;
+
+public class RecordInterface {
+
+ interface Human {
+ default void printHuman() {
+ System.out.println("Human");
+ }
+ }
+
+ record Person(String name, int age) implements Human {}
+
+ public static void main(String[] args) {
+ Person janeDoe = new Person("Jane Doe", 42);
+ janeDoe.printHuman();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 11cebfd..ff10302 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -44,7 +44,6 @@
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
-import java.util.Set;
import java.util.function.Predicate;
import java.util.zip.ZipFile;
import org.junit.Test;
@@ -466,15 +465,10 @@
class MultiTypeConsumer implements DexIndexedConsumer, DexFilePerClassFileConsumer {
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {}
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {}
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {}
@Override
public void finished(DiagnosticsHandler handler) {
diff --git a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
index 6ed73d8..e8a4d1d 100644
--- a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.utils.BooleanUtils;
import java.nio.file.Paths;
import java.util.Collection;
-import java.util.Set;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,15 +59,11 @@
.setProgramConsumer(
new DexIndexedConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- int fileIndex,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
Marker marker;
try {
Collection<Marker> markers =
- ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData());
+ ExtractMarker.extractMarkerFromDexProgramData(data.getByteDataCopy());
assertEquals(1, markers.size());
marker = markers.iterator().next();
} catch (Exception e) {
@@ -104,12 +99,11 @@
.setProgramConsumer(
new ClassFileConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ public void acceptClassFile(ClassFileConsumerData data) {
Marker marker;
try {
Collection<Marker> markers =
- ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData());
+ ExtractMarker.extractMarkerFromClassProgramData(data.getByteDataCopy());
assertEquals(1, markers.size());
marker = markers.iterator().next();
} catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java b/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
index f0b68de..5be0095 100644
--- a/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
@@ -63,15 +63,11 @@
.setProgramConsumer(
new DexIndexedConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- int fileIndex,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
Marker marker;
try {
Collection<Marker> markers =
- ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData());
+ ExtractMarker.extractMarkerFromDexProgramData(data.getByteDataCopy());
assertEquals(1, markers.size());
marker = markers.iterator().next();
} catch (Exception e) {
@@ -111,12 +107,11 @@
.setProgramConsumer(
new ClassFileConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ public void acceptClassFile(ClassFileConsumerData data) {
Marker marker;
try {
Collection<Marker> markers =
- ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData());
+ ExtractMarker.extractMarkerFromClassProgramData(data.getByteDataCopy());
assertEquals(1, markers.size());
marker = markers.iterator().next();
} catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java b/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java
deleted file mode 100644
index 90343b7..0000000
--- a/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2016, 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;
-
-import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.DexParser;
-import com.android.tools.r8.dex.DexSection;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class R8CodeCanonicalizationTest extends TestBase {
-
- private static final Path SOURCE_DEX = Paths.get(
- ToolHelper.EXAMPLES_BUILD_DIR, "invokeempty", "classes.dex");
-
- private int readNumberOfCodes(Path file) throws IOException {
- DexSection[] dexSections = DexParser.parseMapFrom(file);
- for (DexSection dexSection : dexSections) {
- if (dexSection.type == Constants.TYPE_CODE_ITEM) {
- return dexSection.length;
- }
- }
- return 0;
- }
-
- @Test
- public void testNumberOfCodeItemsUnchanged() throws Exception {
- int numberOfCodes = readNumberOfCodes(SOURCE_DEX);
- R8Command.Builder builder = R8Command.builder()
- .setDisableTreeShaking(true)
- .setDisableMinification(true)
- .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
- .setOutput(temp.getRoot().toPath(), OutputMode.DexIndexed);
- ToolHelper.getAppBuilder(builder).addProgramFiles(SOURCE_DEX);
- R8.run(builder.build());
-
- int newNumberOfCodes = readNumberOfCodes(
- Paths.get(temp.getRoot().getCanonicalPath(), "classes.dex"));
- Assert.assertEquals("Number of codeitems does not change.", numberOfCodes, newNumberOfCodes);
- }
-
-}
diff --git a/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java b/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java
index 32f0871..d4ab329 100644
--- a/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.dex.Marker;
import java.util.Collection;
-import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -40,11 +39,10 @@
}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
try {
Collection<Marker> markers =
- ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData());
+ ExtractMarker.extractMarkerFromDexProgramData(data.getByteDataCopy());
assertEquals(1, markers.size());
marker = markers.iterator().next();
} catch (Exception e) {
@@ -67,10 +65,10 @@
}
@Override
- public void accept(ByteDataView data, String descriptors, DiagnosticsHandler handler) {
+ public void acceptClassFile(ClassFileConsumerData data) {
try {
Collection<Marker> markers =
- ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData());
+ ExtractMarker.extractMarkerFromClassProgramData(data.getByteDataCopy());
assertEquals(1, markers.size());
marker = markers.iterator().next();
} catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index da660e7..a1a6580 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -100,7 +100,8 @@
DexVm.Version.V9_0_0,
DexVm.Version.V10_0_0,
DexVm.Version.V12_0_0,
- DexVm.Version.V13_0_0);
+ DexVm.Version.V13_0_0,
+ DexVm.Version.V14_0_0);
private static final String JUNIT_TEST_RUNNER = "org.junit.runner.JUnitCore";
private static final String JUNIT_JAR = "third_party/junit/junit-4.13-beta-2.jar";
@@ -184,13 +185,15 @@
.put(
"098-ddmc",
TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V12_0_0, DexVm.Version.V13_0_0)))
+ TestCondition.runtimes(
+ DexVm.Version.V12_0_0, DexVm.Version.V13_0_0, DexVm.Version.V14_0_0)))
// TODO(b/197079442): Triage - fails with "java.lang.NoSuchMethodException:
// org.apache.harmony.dalvik.ddmc.DdmVmInternal.enableRecentAllocations [boolean]"
.put(
"145-alloc-tracking-stress",
TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V12_0_0, DexVm.Version.V13_0_0)))
+ TestCondition.runtimes(
+ DexVm.Version.V12_0_0, DexVm.Version.V13_0_0, DexVm.Version.V14_0_0)))
.build();
// Tests that are flaky with the Art version we currently use.
@@ -496,6 +499,7 @@
static {
ImmutableMap.Builder<DexVm.Version, List<String>> builder = ImmutableMap.builder();
builder
+ .put(DexVm.Version.V14_0_0, ImmutableList.of("543-env-long-ref", "518-null-array-get"))
.put(DexVm.Version.V13_0_0, ImmutableList.of("543-env-long-ref", "518-null-array-get"))
.put(DexVm.Version.V12_0_0, ImmutableList.of("543-env-long-ref", "518-null-array-get"))
.put(
@@ -832,7 +836,8 @@
DexVm.Version.V5_1_1,
DexVm.Version.V6_0_1,
DexVm.Version.V7_0_0,
- DexVm.Version.V13_0_0)),
+ DexVm.Version.V13_0_0,
+ DexVm.Version.V14_0_0)),
TestCondition.match(
TestCondition.compilers(
CompilerUnderTest.R8,
@@ -861,7 +866,8 @@
DexVm.Version.V9_0_0,
DexVm.Version.V10_0_0,
DexVm.Version.V12_0_0,
- DexVm.Version.V13_0_0)))
+ DexVm.Version.V13_0_0,
+ DexVm.Version.V14_0_0)))
.put("454-get-vreg", TestCondition.match(TestCondition.R8DEX_COMPILER))
// Fails: regs_jni.cc:42] Check failed: GetVReg(m, 0, kIntVReg, &value)
// The R8/D8 code does not put values in the same registers as the tests expects.
@@ -878,7 +884,8 @@
DexVm.Version.V9_0_0,
DexVm.Version.V10_0_0,
DexVm.Version.V12_0_0,
- DexVm.Version.V13_0_0)))
+ DexVm.Version.V13_0_0,
+ DexVm.Version.V14_0_0)))
.put("457-regs", TestCondition.match(TestCondition.R8DEX_COMPILER))
// Class not found.
.put("529-checker-unresolved", TestCondition.any())
diff --git a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
index a4cbbc2..a89ee46 100644
--- a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
@@ -132,29 +132,41 @@
private static final Map<DexVm.Version, Map<String, String>> customProcessedOutputExpectation =
ImmutableMap.of(
Version.V4_4_4,
- ImmutableMap.of(
- "bad-codegen", "java.lang.NullPointerException\n",
- "type-confusion-regression2", "java.lang.NullPointerException\n",
- "type-confusion-regression3", "java.lang.NullPointerException\n",
- "merge-blocks-regression", "java.lang.NullPointerException\n"),
+ ImmutableMap.of(
+ "bad-codegen", "java.lang.NullPointerException\n",
+ "type-confusion-regression2", "java.lang.NullPointerException\n",
+ "type-confusion-regression3", "java.lang.NullPointerException\n",
+ "merge-blocks-regression", "java.lang.NullPointerException\n"),
Version.V4_0_4,
- ImmutableMap.of(
- "bad-codegen", "java.lang.NullPointerException\n",
- "type-confusion-regression2", "java.lang.NullPointerException\n",
- "type-confusion-regression3", "java.lang.NullPointerException\n",
- "merge-blocks-regression", "java.lang.NullPointerException\n"),
+ ImmutableMap.of(
+ "bad-codegen", "java.lang.NullPointerException\n",
+ "type-confusion-regression2", "java.lang.NullPointerException\n",
+ "type-confusion-regression3", "java.lang.NullPointerException\n",
+ "merge-blocks-regression", "java.lang.NullPointerException\n"),
Version.V13_0_0,
- ImmutableMap.of(
- "bad-codegen",
- StringUtils.lines(
- "java.lang.NullPointerException: Attempt to read from field 'Test Test.a'"
- + " on a null object reference in method 'Test TestObject.a(Test,"
- + " Test, Test, Test, boolean)'"),
- "type-confusion-regression3",
- StringUtils.lines(
- "java.lang.NullPointerException: Attempt to read from field 'byte[]"
- + " Test.a' on a null object reference in method 'int"
- + " TestObject.a(Test, Test)'")));
+ ImmutableMap.of(
+ "bad-codegen",
+ StringUtils.lines(
+ "java.lang.NullPointerException: Attempt to read from field 'Test Test.a'"
+ + " on a null object reference in method 'Test TestObject.a(Test,"
+ + " Test, Test, Test, boolean)'"),
+ "type-confusion-regression3",
+ StringUtils.lines(
+ "java.lang.NullPointerException: Attempt to read from field 'byte[]"
+ + " Test.a' on a null object reference in method 'int"
+ + " TestObject.a(Test, Test)'")),
+ Version.V14_0_0,
+ ImmutableMap.of(
+ "bad-codegen",
+ StringUtils.lines(
+ "java.lang.NullPointerException: Attempt to read from field 'Test Test.a'"
+ + " on a null object reference in method 'Test TestObject.a(Test,"
+ + " Test, Test, Test, boolean)'"),
+ "type-confusion-regression3",
+ StringUtils.lines(
+ "java.lang.NullPointerException: Attempt to read from field 'byte[]"
+ + " Test.a' on a null object reference in method 'int"
+ + " TestObject.a(Test, Test)'")));
// Tests where the input fails with a verification error on Dalvik instead of the
// expected runtime exception.
diff --git a/src/test/java/com/android/tools/r8/TestCondition.java b/src/test/java/com/android/tools/r8/TestCondition.java
index e4cec10..a23c980 100644
--- a/src/test/java/com/android/tools/r8/TestCondition.java
+++ b/src/test/java/com/android/tools/r8/TestCondition.java
@@ -27,6 +27,7 @@
ART_V10_0_0,
ART_V12_0_0,
ART_V13_0_0,
+ ART_V14_0_0,
ART_DEFAULT,
ART_MASTER,
JAVA;
@@ -56,6 +57,8 @@
return ART_V12_0_0;
case V13_0_0:
return ART_V13_0_0;
+ case V14_0_0:
+ return ART_V14_0_0;
case DEFAULT:
return ART_DEFAULT;
case MASTER:
diff --git a/src/test/java/com/android/tools/r8/TestParameters.java b/src/test/java/com/android/tools/r8/TestParameters.java
index a05309c..c22f43e 100644
--- a/src/test/java/com/android/tools/r8/TestParameters.java
+++ b/src/test/java/com/android/tools/r8/TestParameters.java
@@ -105,6 +105,11 @@
return false;
}
+ public boolean runtimeWithClassValue() {
+ assert isCfRuntime() || isDexRuntime();
+ return isCfRuntime() || getDexRuntimeVersion().isNewerThanOrEqual(DexVm.Version.V14_0_0);
+ }
+
// Convenience predicates.
public boolean isDexRuntime() {
return runtime.isDex();
@@ -127,7 +132,11 @@
}
public boolean isDexRuntimeVersion(DexVm.Version vm) {
- return isDexRuntime() && vm == getDexRuntimeVersion();
+ return isDexRuntime() && getDexRuntimeVersion().isEqualTo(vm);
+ }
+
+ public boolean isDexRuntimeVersionNewerThanOrEqual(DexVm.Version vm) {
+ return isDexRuntime() && getDexRuntimeVersion().isNewerThanOrEqual(vm);
}
public boolean isNoneRuntime() {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 459fbce..51ed733 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -92,13 +92,26 @@
static final Path[] EMPTY_PATH = {};
+ public static boolean isNewGradleSetup() {
+ return "true".equals(System.getenv("USE_NEW_GRADLE_SETUP"));
+ }
+
+ public static String getProjectRoot() {
+ String property = System.getProperty("user.dir");
+ if (property.endsWith("d8_r8/test")) {
+ return "../../";
+ }
+ return "";
+ }
+
public static final String SOURCE_DIR = "src/main/java/";
public static final String RESOURCES_DIR = "src/main/resources/";
public static final String BUILD_DIR = "build/";
+ public static final String TEST_MODULE_DIR = getProjectRoot() + "d8_r8/test_modules/";
public static final String GENERATED_TEST_BUILD_DIR = BUILD_DIR + "generated/test/";
public static final String LIBS_DIR = BUILD_DIR + "libs/";
- public static final String THIRD_PARTY_DIR = "third_party/";
- public static final String TOOLS_DIR = "tools/";
+ public static final String THIRD_PARTY_DIR = getProjectRoot() + "third_party/";
+ public static final String TOOLS_DIR = getProjectRoot() + "tools/";
public static final String TESTS_DIR = "src/test/";
public static final String TESTS_SOURCE_DIR = "src/test/java";
public static final String EXAMPLES_DIR = TESTS_DIR + "examples/";
@@ -137,29 +150,33 @@
public static final String DEFAULT_PROGUARD_MAP_FILE = "proguard.map";
public static final String CORE_LAMBDA_STUBS =
- "third_party/core-lambda-stubs/core-lambda-stubs.jar";
- public static final String JSR223_RI_JAR = "third_party/jsr223-api-1.0/jsr223-api-1.0.jar";
+ THIRD_PARTY_DIR + "core-lambda-stubs/core-lambda-stubs.jar";
+ public static final String JSR223_RI_JAR = THIRD_PARTY_DIR + "jsr223-api-1.0/jsr223-api-1.0.jar";
public static final String RHINO_ANDROID_JAR =
- "third_party/rhino-android-1.1.1/rhino-android-1.1.1.jar";
- public static final String RHINO_JAR = "third_party/rhino-1.7.10/rhino-1.7.10.jar";
+ THIRD_PARTY_DIR + "rhino-android-1.1.1/rhino-android-1.1.1.jar";
+ public static final String RHINO_JAR = THIRD_PARTY_DIR + "rhino-1.7.10/rhino-1.7.10.jar";
public static final String K2JVMCompiler = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler";
- private static final String ANDROID_JAR_PATTERN = "third_party/android_jar/lib-v%d/android.jar";
+ private static final String ANDROID_JAR_PATTERN =
+ THIRD_PARTY_DIR + "android_jar/lib-v%d/android.jar";
private static final String ANDROID_API_VERSIONS_XML_PATTERN =
- "third_party/android_jar/lib-v%d/api-versions.xml";
+ THIRD_PARTY_DIR + "android_jar/lib-v%d/api-versions.xml";
private static final AndroidApiLevel DEFAULT_MIN_SDK = AndroidApiLevel.I;
- public static final String OPEN_JDK_DIR = "third_party/openjdk/";
+ public static final String OPEN_JDK_DIR = THIRD_PARTY_DIR + "openjdk/";
public static final String JAVA_8_RUNTIME = OPEN_JDK_DIR + "openjdk-rt-1.8/rt.jar";
public static final String JDK_11_TESTS_DIR = OPEN_JDK_DIR + "jdk-11-test/";
public static final String JDK_11_TIME_TESTS_DIR = JDK_11_TESTS_DIR + "java/time/";
- private static final String PROGUARD5_2_1 = "third_party/proguard/proguard5.2.1/bin/proguard";
- private static final String PROGUARD6_0_1 = "third_party/proguard/proguard6.0.1/bin/proguard";
+ private static final String PROGUARD5_2_1 =
+ THIRD_PARTY_DIR + "proguard/proguard5.2.1/bin/proguard";
+ private static final String PROGUARD6_0_1 =
+ THIRD_PARTY_DIR + "proguard/proguard6.0.1/bin/proguard";
private static final String PROGUARD = PROGUARD5_2_1;
public static final Path JACOCO_ROOT = Paths.get("third_party", "jacoco", "0.8.6");
public static final Path JACOCO_AGENT = JACOCO_ROOT.resolve(Paths.get("lib", "jacocoagent.jar"));
public static final Path JACOCO_CLI = JACOCO_ROOT.resolve(Paths.get("lib", "jacococli.jar"));
- public static final String PROGUARD_SETTINGS_FOR_INTERNAL_APPS = "third_party/proguardsettings/";
+ public static final String PROGUARD_SETTINGS_FOR_INTERNAL_APPS =
+ THIRD_PARTY_DIR + "proguardsettings/";
public static final Path RETRACE_MAPS_DIR = Paths.get(THIRD_PARTY_DIR, "r8mappings");
@@ -256,6 +273,8 @@
ART_12_0_0_HOST(Version.V12_0_0, Kind.HOST),
ART_13_0_0_TARGET(Version.V13_0_0, Kind.TARGET),
ART_13_0_0_HOST(Version.V13_0_0, Kind.HOST),
+ ART_14_0_0_TARGET(Version.V14_0_0, Kind.TARGET),
+ ART_14_0_0_HOST(Version.V14_0_0, Kind.HOST),
ART_MASTER_TARGET(Version.MASTER, Kind.TARGET),
ART_MASTER_HOST(Version.MASTER, Kind.HOST);
@@ -276,6 +295,7 @@
V10_0_0("10.0.0"),
V12_0_0("12.0.0"),
V13_0_0("13.0.0"),
+ V14_0_0("14.0.0"),
MASTER("master");
/** This should generally be the latest DEX VM fully supported. */
@@ -338,7 +358,7 @@
}
public static Version last() {
- return V13_0_0;
+ return V14_0_0;
}
public static Version master() {
@@ -609,12 +629,11 @@
}
}
- private static final String TOOLS = "tools";
-
private static final Map<DexVm, String> ART_DIRS =
ImmutableMap.<DexVm, String>builder()
.put(DexVm.ART_DEFAULT, "art")
.put(DexVm.ART_MASTER_HOST, "host/art-master")
+ .put(DexVm.ART_14_0_0_HOST, "host/art-14.0.0-dp1")
.put(DexVm.ART_13_0_0_HOST, "host/art-13.0.0")
.put(DexVm.ART_12_0_0_HOST, "host/art-12.0.0-beta4")
.put(DexVm.ART_10_0_0_HOST, "art-10.0.0")
@@ -630,6 +649,7 @@
ImmutableMap.<DexVm, String>builder()
.put(DexVm.ART_DEFAULT, "bin/art")
.put(DexVm.ART_MASTER_HOST, "bin/art")
+ .put(DexVm.ART_14_0_0_HOST, "bin/art")
.put(DexVm.ART_13_0_0_HOST, "bin/art")
.put(DexVm.ART_12_0_0_HOST, "bin/art")
.put(DexVm.ART_10_0_0_HOST, "bin/art")
@@ -645,6 +665,7 @@
private static final Map<DexVm, String> ART_BINARY_VERSIONS_X64 =
ImmutableMap.<DexVm, String>builder()
.put(DexVm.ART_DEFAULT, "bin/art")
+ .put(DexVm.ART_14_0_0_HOST, "bin/art")
.put(DexVm.ART_13_0_0_HOST, "bin/art")
.put(DexVm.ART_12_0_0_HOST, "bin/art")
.put(DexVm.ART_10_0_0_HOST, "bin/art")
@@ -679,6 +700,7 @@
ImmutableMap.Builder<DexVm, List<String>> builder = ImmutableMap.builder();
builder
.put(DexVm.ART_DEFAULT, ART_BOOT_LIBS)
+ .put(DexVm.ART_14_0_0_HOST, NEWER_ART_BOOT_LIBS)
.put(DexVm.ART_13_0_0_HOST, NEWER_ART_BOOT_LIBS)
.put(DexVm.ART_12_0_0_HOST, NEWER_ART_BOOT_LIBS)
.put(DexVm.ART_10_0_0_HOST, ART_BOOT_LIBS)
@@ -698,6 +720,7 @@
ImmutableMap.Builder<DexVm, String> builder = ImmutableMap.builder();
builder
.put(DexVm.ART_DEFAULT, "angler")
+ .put(DexVm.ART_14_0_0_HOST, "redfin")
.put(DexVm.ART_13_0_0_HOST, "redfin")
.put(DexVm.ART_12_0_0_HOST, "redfin")
.put(DexVm.ART_10_0_0_HOST, "coral")
@@ -715,7 +738,7 @@
private static Path getDexVmPath(DexVm vm) {
DexVm.Version version = vm.getVersion();
- Path base = Paths.get(TOOLS, "linux");
+ Path base = Paths.get(TOOLS_DIR, "linux");
switch (version) {
case DEFAULT:
return base.resolve("art");
@@ -731,6 +754,7 @@
case V12_0_0:
return base.resolve("host").resolve("art-12.0.0-beta4");
case V13_0_0:
+ case V14_0_0:
case MASTER:
return base.resolve("host").resolve("art-" + version);
default:
@@ -765,6 +789,7 @@
return "arm64";
case V12_0_0:
case V13_0_0:
+ case V14_0_0:
case MASTER:
return "x86_64";
default:
@@ -772,10 +797,6 @@
}
}
- private static Path getProductBootImagePath(DexVm vm) {
- return getProductPath(vm).resolve("system").resolve("framework").resolve("boot.art");
- }
-
public static byte[] getClassAsBytes(Class clazz) throws IOException {
return Files.readAllBytes(getClassFileForTestClass(clazz));
}
@@ -799,7 +820,7 @@
}
if (isLinux() || isMac()) {
// The Linux version is used on Mac, where it is run in a Docker container.
- return TOOLS + "/linux/" + dir;
+ return TOOLS_DIR + "/linux/" + dir;
}
fail("Unsupported platform, we currently only support mac and linux: " + getPlatform());
return ""; //never here
@@ -840,7 +861,7 @@
private static Path getDxExecutablePath() {
String toolsDir = toolsDir();
String executableName = toolsDir.equals("windows") ? "dx.bat" : "dx";
- return Paths.get(TOOLS, toolsDir(), "dx", "bin", executableName);
+ return Paths.get(TOOLS_DIR, toolsDir(), "dx", "bin", executableName);
}
public static String getArtBinary(DexVm version) {
@@ -895,7 +916,7 @@
private static Path getAndroidJarPath(AndroidApiLevel apiLevel) {
if (apiLevel == AndroidApiLevel.MASTER) {
- return Paths.get("third_party/android_jar/lib-master/android.jar");
+ return Paths.get(THIRD_PARTY_DIR + "android_jar/lib-master/android.jar");
}
String jar = String.format(
ANDROID_JAR_PATTERN,
@@ -1058,6 +1079,8 @@
switch (dexVm.version) {
case MASTER:
return AndroidApiLevel.MASTER;
+ case V14_0_0:
+ return AndroidApiLevel.U;
case V13_0_0:
return AndroidApiLevel.T;
case V12_0_0:
@@ -1135,7 +1158,11 @@
}
public static Path getClassPathForTests() {
- return Paths.get(BUILD_DIR, "classes", "java", "test");
+ if (isNewGradleSetup()) {
+ return Paths.get(TEST_MODULE_DIR, "tests_java_8", "build", "classes", "java", "main");
+ } else {
+ return Paths.get(BUILD_DIR, "classes", "java", "test");
+ }
}
private static List<String> getNamePartsForTestPackage(Package pkg) {
@@ -1201,7 +1228,7 @@
public static Collection<Path> getClassFilesForInnerClasses(Collection<Class<?>> classes)
throws IOException {
Set<Path> paths = new HashSet<>();
- for (Class clazz : classes) {
+ for (Class<?> clazz : classes) {
Path path = ToolHelper.getClassFileForTestClass(clazz);
String prefix = path.toString().replace(CLASS_EXTENSION, "$");
paths.addAll(
diff --git a/src/test/java/com/android/tools/r8/androidapi/GenerateCovariantReturnTypeMethodsTest.java b/src/test/java/com/android/tools/r8/androidapi/GenerateCovariantReturnTypeMethodsTest.java
index cf867dd..df687ed 100644
--- a/src/test/java/com/android/tools/r8/androidapi/GenerateCovariantReturnTypeMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/androidapi/GenerateCovariantReturnTypeMethodsTest.java
@@ -68,7 +68,7 @@
Paths.get(ToolHelper.SOURCE_DIR)
.resolve(PACKAGE_NAME.replace('.', '/'))
.resolve(CLASS_NAME + ".java");
- private static final AndroidApiLevel GENERATED_FOR_API_LEVEL = AndroidApiLevel.T;
+ private static final AndroidApiLevel GENERATED_FOR_API_LEVEL = AndroidApiLevel.U;
@Parameter public TestParameters parameters;
@@ -79,7 +79,7 @@
@Test
public void testLibCoreNeedsUpgrading() {
- assertEquals(GENERATED_FOR_API_LEVEL, AndroidApiLevel.LATEST);
+ assertEquals(GENERATED_FOR_API_LEVEL, AndroidApiLevel.API_DATABASE_LEVEL);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/apimodel/ClassValueTest.java b/src/test/java/com/android/tools/r8/apimodel/ClassValueTest.java
index 091cff8..f247e38 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ClassValueTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ClassValueTest.java
@@ -68,7 +68,10 @@
.compile()
.inspect(this::computeValuePresent)
.run(parameters.getRuntime(), TestClass.class)
- .assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
+ .applyIf(
+ parameters.runtimeWithClassValue(),
+ r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
+ r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
}
@Test
@@ -83,7 +86,7 @@
.inspect(this::computeValueAbsent)
.run(parameters.getRuntime(), TestClass.class)
.applyIf(
- parameters.isCfRuntime(),
+ parameters.runtimeWithClassValue(),
r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class),
r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
}
@@ -132,7 +135,7 @@
.inspect(this::computeValueAbsent)
.run(parameters.getRuntime(), TestClass.class)
.applyIf(
- parameters.isCfRuntime(),
+ parameters.runtimeWithClassValue(),
r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class),
r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
}
@@ -177,7 +180,7 @@
.inspect(this::computeValuePresent)
.run(parameters.getRuntime(), TestClass.class)
.applyIf(
- parameters.isCfRuntime(),
+ parameters.runtimeWithClassValue(),
r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
index 2673e46..13a5073 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.cf.varhandle;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.examples.jdk9.VarHandle;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
@@ -73,6 +74,9 @@
@Override
protected String getExpectedOutputForArtImplementation() {
assert parameters.isDexRuntime();
- return StringUtils.lines(EXPECTED_OUTPUT.trim(), "Art implementation", "Art implementation");
+ return parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V14_0_0)
+ ? StringUtils.lines(
+ EXPECTED_OUTPUT.trim(), "Reference implementation", "Reference implementation")
+ : StringUtils.lines(EXPECTED_OUTPUT.trim(), "Art implementation", "Art implementation");
}
}
diff --git a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
index fd3e16d..f4ef14b 100644
--- a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
+++ b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.compilerapi.assertionconfiguration.AssertionConfigurationTest;
import com.android.tools.r8.compilerapi.classconflictresolver.ClassConflictResolverTest;
import com.android.tools.r8.compilerapi.desugardependencies.DesugarDependenciesTest;
+import com.android.tools.r8.compilerapi.dexconsumers.PerClassSyntheticContextsTest;
import com.android.tools.r8.compilerapi.diagnostics.ProguardKeepRuleDiagnosticsApiTest;
import com.android.tools.r8.compilerapi.diagnostics.UnsupportedFeaturesDiagnosticApiTest;
import com.android.tools.r8.compilerapi.globalsynthetics.GlobalSyntheticsTest;
@@ -58,7 +59,8 @@
ArtProfilesForRewritingApiTest.ApiTest.class,
StartupProfileApiTest.ApiTest.class,
ClassConflictResolverTest.ApiTest.class,
- ProguardKeepRuleDiagnosticsApiTest.ApiTest.class);
+ ProguardKeepRuleDiagnosticsApiTest.ApiTest.class,
+ PerClassSyntheticContextsTest.ApiTest.class);
private final TemporaryFolder temp;
diff --git a/src/test/java/com/android/tools/r8/compilerapi/dexconsumers/PerClassSyntheticContextsTest.java b/src/test/java/com/android/tools/r8/compilerapi/dexconsumers/PerClassSyntheticContextsTest.java
new file mode 100644
index 0000000..69f7b9b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/dexconsumers/PerClassSyntheticContextsTest.java
@@ -0,0 +1,111 @@
+// 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.compilerapi.dexconsumers;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.ClassFileConsumerData;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DexFilePerClassFileConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import org.junit.Test;
+
+public class PerClassSyntheticContextsTest extends CompilerApiTestRunner {
+
+ public PerClassSyntheticContextsTest(TestParameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public Class<? extends CompilerApiTest> binaryTestClass() {
+ return ApiTest.class;
+ }
+
+ @Test
+ public void test() throws Exception {
+ // First compile to CF such that we have an input class that has a synthetic context.
+ ClassReference backport = SyntheticItemsTestUtils.syntheticBackportClass(UsesBackport.class, 0);
+ Map<String, byte[]> outputs = new HashMap<>();
+ testForD8(Backend.CF)
+ .addProgramClasses(UsesBackport.class)
+ .setIntermediate(true)
+ .setMinApi(1)
+ .setProgramConsumer(
+ new ClassFileConsumer() {
+
+ @Override
+ public void acceptClassFile(ClassFileConsumerData data) {
+ outputs.put(data.getClassDescriptor(), data.getByteDataCopy());
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ })
+ .compile()
+ .writeToZip();
+ // Run using the API test to obtain the backport context.
+ new ApiTest(ApiTest.PARAMETERS)
+ .run(
+ outputs.get(backport.getDescriptor()),
+ context -> assertEquals(descriptor(UsesBackport.class), context));
+ }
+
+ public static class UsesBackport {
+ public static void foo() {
+ Boolean.compare(true, false);
+ }
+ }
+
+ public static class ApiTest extends CompilerApiTest {
+
+ public ApiTest(Object parameters) {
+ super(parameters);
+ }
+
+ public void run(byte[] input, Consumer<String> syntheticContext) throws Exception {
+ D8.run(
+ D8Command.builder()
+ .addClassProgramData(input, Origin.unknown())
+ .addLibraryFiles(getJava8RuntimeJar())
+ .setMinApiLevel(1)
+ .setProgramConsumer(
+ new DexFilePerClassFileConsumer() {
+ @Override
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ syntheticContext.accept(data.getSynthesizingContextForPrimaryClass());
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {
+ // nothing to finish up.
+ }
+ })
+ .build());
+ }
+
+ @Test
+ public void test() throws Exception {
+ byte[] input = getBytesForClass(getMockClass());
+ run(
+ input,
+ context -> {
+ if (context != null) {
+ throw new RuntimeException("unexpected");
+ }
+ });
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
index f413f98..7c82964 100644
--- a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
+++ b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
@@ -5,18 +5,17 @@
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DexIndexedConsumerData;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.Set;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -77,8 +76,7 @@
boolean hasOutput = false;
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
hasOutput = true;
}
diff --git a/src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java b/src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java
index 51e8ab2..7a73a31 100644
--- a/src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/debug/InterfaceMethodTest.java
@@ -47,9 +47,12 @@
@Test
public void testDefaultMethod() throws Throwable {
- // TODO(b/244683447): This test fails on ART 13 when checking current method in doSomething.
+ // TODO(b/244683447): This test fails on Art 13 and Art 14 when checking current method in
+ // doSomething.
assumeTrue(
- parameters.isCfRuntime() || !parameters.getDexRuntimeVersion().isEqualTo(Version.V13_0_0));
+ parameters.isCfRuntime()
+ || !(parameters.getDexRuntimeVersion().isEqualTo(Version.V13_0_0)
+ || parameters.getDexRuntimeVersion().isEqualTo(Version.V14_0_0)));
testForRuntime(parameters)
.addProgramFiles(JAR)
.run(parameters.getRuntime(), debuggeeClass)
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
index 901e412..2205c9c 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
@@ -259,7 +259,9 @@
public void testNestedInlining() throws Throwable {
assumeTrue(
"b/244704042: Incorrect step-into StringBuilder.",
- parameters.isCfRuntime() || !parameters.getDexRuntimeVersion().isEqualTo(Version.V13_0_0));
+ parameters.isCfRuntime()
+ || !(parameters.getDexRuntimeVersion().isEqualTo(Version.V13_0_0)
+ || parameters.getDexRuntimeVersion().isEqualTo(Version.V14_0_0)));
// Count the number of lines in the source file. This is needed to check that inlined code
// refers to non-existing line numbers.
Path sourceFilePath =
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
index efcc639..2bc0090 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
@@ -6,11 +6,10 @@
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileConsumer.ForwardingConsumer;
+import com.android.tools.r8.ClassFileConsumerData;
import com.android.tools.r8.D8TestCompileResult;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -91,9 +90,8 @@
.setProgramConsumer(
new ClassFileConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- ByteDataView data, String descriptor, DiagnosticsHandler handler) {
- checkDeprecatedAttributes(data.getBuffer());
+ public void acceptClassFile(ClassFileConsumerData data) {
+ checkDeprecatedAttributes(data.getByteDataView().getBuffer());
}
})
.compile();
@@ -128,8 +126,8 @@
builder.setProgramConsumer(
new ForwardingConsumer(null) {
@Override
- public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
- checkDeprecatedAttributes(data.getBuffer());
+ public void acceptClassFile(ClassFileConsumerData data) {
+ checkDeprecatedAttributes(data.getByteDataView().getBuffer());
}
});
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
index ed2dd4e..9be08a2 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
@@ -10,11 +10,11 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.ClassFileConsumerData;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DexFilePerClassFileConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -247,21 +247,16 @@
firstRoundOutput.isCf()
? new ClassFileConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- ByteDataView data, String descriptor, DiagnosticsHandler handler) {
- byte[] bytes = data.copyByteData();
+ public void acceptClassFile(ClassFileConsumerData data) {
+ byte[] bytes = data.getByteDataCopy();
assert bytes != null;
outputsRoundOne.add(bytes);
}
}
: new DexFilePerClassFileConsumer.ForwardingConsumer(null) {
@Override
- public void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- byte[] bytes = data.copyByteData();
+ public void acceptDexFile(DexFilePerClassFileConsumerData data) {
+ byte[] bytes = data.getByteDataCopy();
assert bytes != null;
outputsRoundOne.add(bytes);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
index 5369238..4a55fc2 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
@@ -9,8 +9,8 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DexIndexedConsumerData;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.GenerateMainDexListRunResult;
import com.android.tools.r8.OutputMode;
@@ -361,13 +361,12 @@
Set<String> mainDexDescriptors;
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
- if (fileIndex == 0) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ if (data.getFileIndex() == 0) {
assertNull(mainDexBytes);
assertNull(mainDexDescriptors);
- mainDexBytes = data.copyByteData();
- mainDexDescriptors = descriptors;
+ mainDexBytes = data.getByteDataCopy();
+ mainDexDescriptors = data.getClassDescriptors();
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava17Test.java b/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava17Test.java
index fde89f0..8f9332d 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava17Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava17Test.java
@@ -34,7 +34,6 @@
super(parameters, Math.class, TEST_JAR, "backport.MathBackportJava17Main");
// Math.absExact.
- // The exact number needs to be updated once we test Android U.
- registerTarget(AndroidApiLevel.U, 27);
+ registerTarget(AndroidApiLevel.U, 8);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava17Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava17Test.java
index d54a044..4a5345fe 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava17Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava17Test.java
@@ -35,7 +35,6 @@
public ObjectsBackportJava17Test(TestParameters parameters) {
super(parameters, Objects.class, TEST_JAR, TEST_CLASS);
// Objects.checkFromIndexSize, Objects.checkFromToIndex, Objects.checkIndex.
- // The exact number needs to be updated once we test Android U.
- registerTarget(AndroidApiLevel.U, 28);
+ registerTarget(AndroidApiLevel.U, 21);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/StreamBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/StreamBackportJava9Test.java
index 073c179..5e33276 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/StreamBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/StreamBackportJava9Test.java
@@ -34,12 +34,15 @@
public StreamBackportJava9Test(TestParameters parameters) {
super(parameters, Stream.class, TEST_JAR, "backport.StreamBackportJava9Main");
- // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
- // an actual API level, migrate these tests to StreamBackportTest.
+ // Note: The methods in this test exist from Android U. However, they are only available from
+ // Java 9. When tests build with Java 9 migrate to StreamBackportTest and add insert
+ // StreamBackportJava9Main as an inner class here.
// Available since N as part of library desugaring.
ignoreInvokes("of");
ignoreInvokes("empty");
ignoreInvokes("count");
+
+ registerTarget(AndroidApiLevel.U, 2);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava17Test.java b/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava17Test.java
index 3089d40..c93b1ee 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava17Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava17Test.java
@@ -33,7 +33,6 @@
public StrictMathBackportJava17Test(TestParameters parameters) {
super(parameters, StrictMath.class, TEST_JAR, "backport.StrictMathBackportJava17Main");
- // The exact number needs to be updated once we test Android U.
- registerTarget(AndroidApiLevel.U, 75);
+ registerTarget(AndroidApiLevel.U, 30);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java
index 16021f7..089553b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
import com.android.tools.r8.utils.StringUtils;
@@ -29,6 +30,11 @@
StringUtils.lines("2/3/01 4:05 AM - Feb 3, 1 4:05 AM");
private static final String expectedOutput =
StringUtils.lines("2/3/01, 4:05 AM - Feb 3, 1, 4:05 AM");
+ // From ICU 72, see https://android-review.git.corp.google.com/c/platform/libcore/+/2292140
+ private static final String expectedOutputDesugaredLibNNBSP =
+ StringUtils.lines("2/3/01 4:05\u202FAM - Feb 3, 1 4:05\u202FAM");
+ private static final String expectedOutputNNBSP =
+ StringUtils.lines("2/3/01, 4:05\u202FAM - Feb 3, 1, 4:05\u202FAM");
private final TestParameters parameters;
private final CompilationSpecification compilationSpecification;
@@ -61,9 +67,15 @@
.run(parameters.getRuntime(), TestClass.class)
.assertSuccess();
if (libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
- run.assertSuccessWithOutput(expectedOutputDesugaredLib);
+ run.assertSuccessWithOutput(
+ parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V14_0_0)
+ ? expectedOutputDesugaredLibNNBSP
+ : expectedOutputDesugaredLib);
} else {
- run.assertSuccessWithOutput(expectedOutput);
+ run.assertSuccessWithOutput(
+ parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V14_0_0)
+ ? expectedOutputNNBSP
+ : expectedOutput);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
index 3fd5104..2f65784 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
@@ -9,9 +9,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.DexIndexedConsumerData;
import com.android.tools.r8.L8TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
@@ -22,7 +21,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
-import java.util.Set;
import java.util.zip.ZipFile;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -67,8 +65,7 @@
}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
count++;
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java
index 8b67b20..a2c95c1 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java
@@ -169,7 +169,6 @@
"test.java.time.TestOffsetTime",
"test.java.time.TestClock_Offset",
"test.java.time.TestPeriod",
- "test.java.time.TestClock_System",
"test.java.time.TestOffsetDateTime_instants",
"test.java.time.temporal.TestDateTimeBuilderCombinations",
"test.java.time.temporal.TestJulianFields",
@@ -180,6 +179,12 @@
new String[] {"tck.java.time.TestIsoChronology"};
static final String[] RAW_TEMPORAL_SUCCESSES_UP_TO_11 =
new String[] {"test.java.time.temporal.TestIsoWeekFields"};
+ static final String[] RAW_TEMPORAL_SUCCESSES_UP_TO_14 =
+ new String[] {
+ // Reflective lookup Class.forName("java.time.Clock$SystemClock").getDeclaredField("offset")
+ // fails.
+ "test.java.time.TestClock_System"
+ };
static final String[] FORMAT_CHRONO_SUCCESSES =
new String[] {
"test.java.time.format.TestFractionPrinterParser",
@@ -230,6 +235,10 @@
// In 12 some ISO is supported that other versions do not support.
Collections.addAll(allTests, RAW_TEMPORAL_SUCCESSES_UP_TO_11);
}
+ if (parameters.getDexRuntimeVersion().isOlderThan(Version.V14_0_0)) {
+ // In 14 some reflection used in test fails.
+ Collections.addAll(allTests, RAW_TEMPORAL_SUCCESSES_UP_TO_14);
+ }
// The bridge is always present with JDK11 due to partial desugaring between 26 and 33.
// On JDK8 the bridge is absent in between 26 and 33.
if (libraryDesugaringSpecification != JDK8
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
index d80d81e..541bfea 100644
--- a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
+++ b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
@@ -4,9 +4,11 @@
package com.android.tools.r8.desugar.graph;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.DesugarGraphConsumer;
+import com.android.tools.r8.origin.GlobalSyntheticOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -96,6 +98,12 @@
@Override
public synchronized void accept(Origin dependent, Origin dependency) {
+ // D8/R8 should not report edges synthetic origin.
+ assertNotEquals(dependent, GlobalSyntheticOrigin.instance());
+ assertNotEquals(dependency, GlobalSyntheticOrigin.instance());
+ // D8/R8 may report edges to unknown origin, but that is typically *not* what should be done.
+ assertNotEquals(dependency, Origin.unknown());
+ assertNotEquals(dependent, Origin.unknown());
assertFalse(finished);
dependents.computeIfAbsent(dependency, s -> new HashSet<>()).add(dependent);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/jdk8272564/Jdk8272564Test.java b/src/test/java/com/android/tools/r8/desugar/jdk8272564/Jdk8272564Test.java
index 08e9523..bb58476 100644
--- a/src/test/java/com/android/tools/r8/desugar/jdk8272564/Jdk8272564Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/jdk8272564/Jdk8272564Test.java
@@ -144,7 +144,7 @@
.addProgramFiles(Jdk8272564.jar())
.run(parameters.getRuntime(), Jdk8272564.Main.typeName())
.applyIf(
- parameters.isDexRuntime() && parameters.getApiLevel().isLessThan(AndroidApiLevel.P),
+ parameters.isDexRuntime() && parameters.getApiLevel().isLessThan(AndroidApiLevel.S),
b -> b.inspect(this::assertJdk8272564NotFixedCode),
b -> b.inspect(this::assertJdk8272564FixedCode))
.assertSuccess();
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeInterfaceTest.java
index 3b6ac61..9c36e69 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeInterfaceTest.java
@@ -77,7 +77,7 @@
public void testD8() throws Exception {
parameters.assumeDexRuntime();
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForD8()
.addProgramClassFileData(
dumpHost(),
@@ -111,8 +111,8 @@
@Test
public void testD8WithClasspathAndMerge() throws Exception {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
Path host =
testForD8()
@@ -199,8 +199,8 @@
@Test
public void testD8WithoutMembersOnClasspath() {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
assertThrows(
CompilationFailedException.class,
@@ -220,8 +220,8 @@
@Test
public void testD8WithoutHostOnClasspath() {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
assertThrows(
CompilationFailedException.class,
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSuperTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSuperTest.java
index b629ed8..36290f2 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSuperTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeSuperTest.java
@@ -69,7 +69,7 @@
public void testD8() throws Exception {
parameters.assumeDexRuntime();
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForD8()
.addProgramClassFileData(dumpHost(), dumpMember(), dumpSubMember())
.setMinApi(parameters)
@@ -101,8 +101,8 @@
@Test
public void testD8WithClasspathAndMerge() throws Exception {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
Path host =
testForD8()
@@ -188,8 +188,8 @@
@Test
public void testD8WithoutMembersOnClasspath() {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
assertThrows(
CompilationFailedException.class,
@@ -209,8 +209,8 @@
@Test
public void testD8WithoutHostOnClasspath() {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
assertThrows(
CompilationFailedException.class,
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeVirtualTest.java
index 6e516a4..9e2d0c0 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexRewriteInvokeVirtualTest.java
@@ -69,7 +69,7 @@
public void testD8() throws Exception {
parameters.assumeDexRuntime();
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForD8()
.addProgramClassFileData(dumpHost(), dumpMember1(), dumpMember2())
.setMinApi(parameters)
@@ -101,8 +101,8 @@
@Test
public void testD8WithClasspathAndMerge() throws Exception {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
Path host =
testForD8()
@@ -188,8 +188,8 @@
@Test
public void testD8WithoutMembersOnClasspath() {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
assertThrows(
CompilationFailedException.class,
@@ -209,8 +209,8 @@
@Test
public void testD8WithoutHostOnClasspath() {
assumeTrue(parameters.isDexRuntime());
- // TODO(sgjesse): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
assertThrows(
CompilationFailedException.class,
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingFieldsTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingFieldsTest.java
index 5bd24bf..4a1e82c 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingFieldsTest.java
@@ -81,7 +81,7 @@
parameters.assumeR8TestParameters();
assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForR8(parameters.getBackend())
.addProgramClassFileData(
dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
@@ -99,7 +99,7 @@
parameters.assumeR8TestParameters();
assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForR8(parameters.getBackend())
.addProgramClassFileData(
dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
@@ -121,7 +121,7 @@
parameters.assumeR8TestParameters();
assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForR8(parameters.getBackend())
.addProgramClassFileData(
dumpHost(ACC_PUBLIC), dumpMember1(ACC_PUBLIC), dumpMember2(ACC_PUBLIC))
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingMethodsTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingMethodsTest.java
index 8d924dc..eca6260 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexShrinkingMethodsTest.java
@@ -80,7 +80,7 @@
parameters.assumeR8TestParameters();
assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForR8(parameters.getBackend())
.addProgramClassFileData(
dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
@@ -98,7 +98,7 @@
parameters.assumeR8TestParameters();
assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForR8(parameters.getBackend())
.addProgramClassFileData(
dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
@@ -120,7 +120,7 @@
parameters.assumeR8TestParameters();
assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
// TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
- assertFalse(parameters.getApiLevel().getLevel() > 33);
+ assertFalse(parameters.getApiLevel().getLevel() > 34);
testForR8(parameters.getBackend())
.addProgramClassFileData(
dumpHost(ACC_PUBLIC), dumpMember1(ACC_PUBLIC), dumpMember2(ACC_PUBLIC))
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexTest.java
index 1c740a4..74ea12f 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestAttributesInDexTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.desugar.nestaccesscontrol.NestAttributesInDexTest.Host.Member1;
import com.android.tools.r8.desugar.nestaccesscontrol.NestAttributesInDexTest.Host.Member2;
import com.android.tools.r8.transformers.ClassFileTransformer;
@@ -62,13 +63,18 @@
private void checkResult(TestRunResult<?> result) {
if (isRuntimeWithNestSupport(parameters.getRuntime())) {
result.assertSuccessWithOutput(EXPECTED_OUTPUT);
+ } else if (parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V14_0_0)) {
+ // TODO(b/247047415): Partial DEX support in Android U DP1 (reflective APIs).
+ result.assertSuccessWithOutput(R8_EXPECTED_OUTPUT);
} else {
result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
}
}
private void checkResultR8(TestRunResult<?> result) {
- if (isRuntimeWithNestSupport(parameters.getRuntime())) {
+ // TODO(b/247047415): Partial DEX support in Android U DP1 (reflective APIs).
+ if (parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V14_0_0)
+ || isRuntimeWithNestSupport(parameters.getRuntime())) {
result.assertSuccessWithOutput(R8_EXPECTED_OUTPUT);
} else {
result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordInterfaceTest.java
new file mode 100644
index 0000000..2136f70
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordInterfaceTest.java
@@ -0,0 +1,166 @@
+// 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.records;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.GlobalSyntheticsConsumer;
+import com.android.tools.r8.R8FullTestBuilder;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.desugar.graph.DesugarGraphTestConsumer;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.synthesis.globals.GlobalSyntheticsTestingConsumer;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+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 RecordInterfaceTest extends TestBase {
+
+ private static final String RECORD_NAME = "RecordInterface";
+ private static final byte[][] PROGRAM_DATA = RecordTestUtils.getProgramData(RECORD_NAME);
+ private static final String MAIN_TYPE = RecordTestUtils.getMainType(RECORD_NAME);
+ private static final String EXPECTED_RESULT = StringUtils.lines("Human");
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ private boolean isCfRuntimeWithNativeRecordSupport() {
+ return parameters.isCfRuntime()
+ && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+ && parameters.getApiLevel().equals(AndroidApiLevel.B);
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ assumeTrue(isCfRuntimeWithNativeRecordSupport());
+ testForJvm(parameters)
+ .addProgramClassFileData(PROGRAM_DATA)
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(PROGRAM_DATA)
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+
+ @Test
+ public void testD8Intermediate() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ DesugarGraphTestConsumer consumer = new DesugarGraphTestConsumer();
+ GlobalSyntheticsTestingConsumer globals = new GlobalSyntheticsTestingConsumer();
+ Path path = compileIntermediate(globals);
+ testForD8()
+ .addProgramFiles(path)
+ .apply(
+ b ->
+ b.getBuilder()
+ .addGlobalSyntheticsResourceProviders(globals.getIndexedModeProvider()))
+ .apply(b -> b.getBuilder().setDesugarGraphConsumer(consumer))
+ .setMinApi(parameters)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ assertNoEdgeToRecord(consumer);
+ }
+
+ @Test
+ public void testD8IntermediateNoDesugaringInStep2() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ DesugarGraphTestConsumer consumer = new DesugarGraphTestConsumer();
+ GlobalSyntheticsTestingConsumer globals = new GlobalSyntheticsTestingConsumer();
+ Path path = compileIntermediate(globals);
+ testForD8()
+ .addProgramFiles(path)
+ .apply(
+ b ->
+ b.getBuilder()
+ .addGlobalSyntheticsResourceProviders(globals.getIndexedModeProvider()))
+ .apply(b -> b.getBuilder().setDesugarGraphConsumer(consumer))
+ .setMinApi(parameters)
+ .setIncludeClassesChecksum(true)
+ // In Android Studio they disable desugaring at this point to improve build speed.
+ .disableDesugaring()
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ assertNoEdgeToRecord(consumer);
+ }
+
+ private Path compileIntermediate(GlobalSyntheticsConsumer globalSyntheticsConsumer)
+ throws Exception {
+ Origin fake = new PathOrigin(Paths.get("origin"));
+ DesugarGraphTestConsumer consumer = new DesugarGraphTestConsumer();
+ Path intermediate =
+ testForD8(Backend.DEX)
+ .apply(
+ b -> {
+ // We avoid unknown origin here since they are not allowed when using a Graph
+ // consumer.
+ for (byte[] programDatum : PROGRAM_DATA) {
+ b.getBuilder().addClassProgramData(programDatum, fake);
+ }
+ })
+ .setMinApi(parameters)
+ .setIntermediate(true)
+ .setIncludeClassesChecksum(true)
+ .apply(b -> b.getBuilder().setGlobalSyntheticsConsumer(globalSyntheticsConsumer))
+ .apply(b -> b.getBuilder().setDesugarGraphConsumer(consumer))
+ .compile()
+ .assertNoMessages()
+ .writeToZip();
+ assertNoEdgeToRecord(consumer);
+ return intermediate;
+ }
+
+ private void assertNoEdgeToRecord(DesugarGraphTestConsumer consumer) {
+ assertEquals(0, consumer.totalEdgeCount());
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ parameters.assumeR8TestParameters();
+ assumeTrue(parameters.isDexRuntime() || isCfRuntimeWithNativeRecordSupport());
+ R8FullTestBuilder builder =
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(PROGRAM_DATA)
+ .setMinApi(parameters)
+ .addKeepMainRule(MAIN_TYPE);
+ if (parameters.isCfRuntime()) {
+ builder
+ .addLibraryFiles(RecordTestUtils.getJdk15LibraryFiles(temp))
+ .compile()
+ .inspect(RecordTestUtils::assertRecordsAreRecords)
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ return;
+ }
+ builder.run(parameters.getRuntime(), MAIN_TYPE).assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/sealed/PermittedSubclassesAttributeInDexTest.java b/src/test/java/com/android/tools/r8/desugar/sealed/PermittedSubclassesAttributeInDexTest.java
index 32cee2a..cc01489 100644
--- a/src/test/java/com/android/tools/r8/desugar/sealed/PermittedSubclassesAttributeInDexTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/sealed/PermittedSubclassesAttributeInDexTest.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.transformers.ClassFileTransformer;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -72,8 +73,11 @@
.compile()
.inspect(this::inspect)
.run(parameters.getRuntime(), TestClass.class)
- // No Art versions have support for sealed classes yet.
- .assertFailureWithErrorThatThrows(NoSuchMethodError.class);
+ .applyIf(
+ // TODO(b/270941147): Partial DEX support in Android U DP1 (reflective APIs).
+ parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V14_0_0),
+ r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
+ r -> r.assertFailureWithErrorThatThrows(NoSuchMethodError.class));
}
public Collection<byte[]> getTransformedClasses() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java b/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java
index 1d8821e..3988efd 100644
--- a/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java
+++ b/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java
@@ -3,10 +3,8 @@
import static junit.framework.TestCase.fail;
import static org.junit.Assume.assumeTrue;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
@@ -92,17 +90,7 @@
builder
.addProgramResourceProvider(ArchiveResourceProvider.fromArchive(featureJar, true))
- .setProgramConsumer(
- new ArchiveConsumer(outputPath, true) {
- @Override
- public void accept(
- int fileIndex,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- super.accept(fileIndex, data, descriptors, handler);
- }
- });
+ .setProgramConsumer(new ArchiveConsumer(outputPath, true));
}
public static FeatureSplit splitWithNonJavaFile(
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnOtherInterfaceTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnOtherInterfaceTest.java
index 475a8e7..c66a13d 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnOtherInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnOtherInterfaceTest.java
@@ -44,7 +44,7 @@
.applyIf(
parameters.isCfRuntime(),
r -> r.assertFailureWithErrorThatThrows(VerifyError.class),
- !(parameters.isDexRuntimeVersion(Version.V13_0_0)
+ !(parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V13_0_0)
&& parameters.canUseDefaultAndStaticInterfaceMethods()),
r -> r.assertSuccessWithOutputLines("Hello World!"),
r -> r.assertFailureWithErrorThatThrows(NoSuchMethodError.class));
@@ -67,7 +67,7 @@
parameters.isDexRuntime() && !parameters.canUseDefaultAndStaticInterfaceMethods(),
r -> r.assertSuccessWithOutputLines("Hello World!"),
parameters.isDexRuntime()
- && !parameters.isDexRuntimeVersion(Version.V13_0_0)
+ && !parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V13_0_0)
&& parameters.canUseDefaultAndStaticInterfaceMethods(),
r -> r.assertFailureWithErrorThatThrows(NullPointerException.class),
r -> r.assertFailureWithErrorThatThrows(NoSuchMethodError.class));
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningRegressionTests.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningRegressionTests.java
index 63c62a5..8f1c4af 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningRegressionTests.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningRegressionTests.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.utils.FileUtils;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
import org.junit.Assume;
import org.junit.Test;
@@ -51,10 +52,12 @@
.get(ToolHelper.EXAMPLES_BUILD_DIR, folder, ToolHelper.DEFAULT_DEX_FILENAME).toString();
Path generatedDexFile = temp.getRoot().toPath().resolve("classes.jar");
app.writeToZipForTesting(generatedDexFile, OutputMode.DexIndexed);
- String artOutput = ToolHelper
- .checkArtOutputIdentical(originalDexFile, generatedDexFile.toString(), mainClass,
+ String artOutput =
+ ToolHelper.runArtNoVerificationErrors(
+ Collections.singletonList(generatedDexFile.toString()),
+ mainClass,
+ null,
ToolHelper.getDexVm());
-
// Compare with Java.
ToolHelper.ProcessResult javaResult = ToolHelper.runJava(jarFile, mainClass);
if (javaResult.exitCode != 0) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java
index 6765723..a53ca72 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java
@@ -94,7 +94,7 @@
private List<String> getExpectedOutputLines() {
if (parameters.isDexRuntime()) {
if (parameters.getDexRuntimeVersion().isEqualTo(Version.V7_0_0)
- || parameters.getDexRuntimeVersion().isEqualTo(Version.V13_0_0)) {
+ || parameters.isDexRuntimeVersionNewerThanOrEqual(Version.V13_0_0)) {
return ImmutableList.of("true");
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java b/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java
index 61c7a61..15fccd2 100644
--- a/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java
@@ -99,6 +99,7 @@
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
.allowDiagnosticMessages()
.allowUnusedDontWarnKotlinReflectJvmInternal(kotlinc.isNot(KOTLINC_1_3_72))
+ .allowUnusedDontWarnJavaLangClassValue()
.applyIf(
parameters.isCfRuntime() && kotlinParameters.isNewerThanOrEqualTo(KOTLINC_1_8_0),
TestShrinkerBuilder::addDontWarnJavaLangInvokeLambdaMetadataFactory)
diff --git a/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java b/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java
index 9a4c93a..32568f9 100644
--- a/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java
@@ -108,7 +108,8 @@
.addKeepEnumsRule()
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
.allowDiagnosticMessages()
- .allowUnusedDontWarnKotlinReflectJvmInternal();
+ .allowUnusedDontWarnKotlinReflectJvmInternal()
+ .allowUnusedDontWarnJavaLangClassValue();
}
@Test
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
index 1abcddd..0bf9bc8 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
@@ -45,22 +45,11 @@
private static final Path JAR_LIBRARY =
Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "memberrebindinglib.jar");
- private enum Frontend {
- DEX, JAR;
-
- @Override
- public String toString() {
- return this == DEX ? ".dex" : ".jar";
- }
- }
-
private final String name;
- private final Frontend kind;
+
private final Backend backend;
- private final Path originalDex;
private final Path programFile;
private final Consumer<CodeInspector> inspection;
- private final Consumer<CodeInspector> originalInspection;
private final int minApiLevel;
@Rule
@@ -68,16 +57,9 @@
public MemberRebindingTest(TestConfiguration configuration) {
this.name = configuration.name;
- this.kind = configuration.kind;
this.backend = configuration.backend;
- originalDex = configuration.getDexPath();
- if (kind == Frontend.DEX) {
- this.programFile = originalDex;
- } else {
- this.programFile = configuration.getJarPath();
- }
+ this.programFile = configuration.getJarPath();
this.inspection = configuration.processedInspection;
- this.originalInspection = configuration.originalInspection;
this.minApiLevel = configuration.getMinApiLevel();
}
@@ -114,36 +96,6 @@
return !invoke.holder().is("java.io.PrintStream");
}
- private static void inspectOriginalMain(CodeInspector inspector) {
- MethodSubject main = inspector.clazz("memberrebinding.Memberrebinding")
- .method(CodeInspector.MAIN);
- Iterator<InvokeInstructionSubject> iterator =
- main.iterateInstructions(MemberRebindingTest::coolInvokes);
- assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
- assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
- assertTrue(iterator.next().holder().is("java.lang.System"));
- assertTrue(iterator.next().holder().is("memberrebindinglib.AnIndependentInterface"));
- assertTrue(iterator.next().holder().is("java.lang.System"));
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
- assertFalse(iterator.hasNext());
- }
-
private static void inspectMain(CodeInspector inspector) {
MethodSubject main = inspector.clazz("memberrebinding.Memberrebinding")
.method(CodeInspector.MAIN);
@@ -178,22 +130,6 @@
assertFalse(iterator.hasNext());
}
- private static void inspectOriginalMain2(CodeInspector inspector) {
- MethodSubject main = inspector.clazz("memberrebinding2.Memberrebinding")
- .method(CodeInspector.MAIN);
- Iterator<FieldAccessInstructionSubject> iterator =
- main.iterateInstructions(InstructionSubject::isFieldAccess);
- // Run through instance put, static put, instance get and instance get.
- for (int i = 0; i < 4; i++) {
- assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding2.subpackage.PublicClass"));
- }
- assertTrue(iterator.next().holder().is("java.lang.System"));
- assertFalse(iterator.hasNext());
- }
-
private static void inspectMain2(CodeInspector inspector) {
MethodSubject main = inspector.clazz("memberrebinding2.Memberrebinding")
.method(CodeInspector.MAIN);
@@ -213,15 +149,6 @@
public static MethodSignature TEST =
new MethodSignature("test", "void", new String[]{});
- private static void inspectOriginal3(CodeInspector inspector) {
- MethodSubject main = inspector.clazz("memberrebinding3.Memberrebinding").method(TEST);
- Iterator<InvokeInstructionSubject> iterator =
- main.iterateInstructions(InstructionSubject::isInvoke);
- assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
- assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
- assertFalse(iterator.hasNext());
- }
private static void inspect3(CodeInspector inspector) {
MethodSubject main = inspector.clazz("memberrebinding3.Memberrebinding").method(TEST);
@@ -233,15 +160,6 @@
assertFalse(iterator.hasNext());
}
- private static void inspectOriginal4(CodeInspector inspector) {
- MethodSubject main = inspector.clazz("memberrebinding4.Memberrebinding").method(TEST);
- Iterator<InvokeInstructionSubject> iterator =
- main.iterateInstructions(InstructionSubject::isInvoke);
- assertTrue(iterator.next().holder().is("memberrebinding4.Memberrebinding$Inner"));
- assertTrue(iterator.next().holder().is("memberrebinding4.subpackage.PublicInterface"));
- assertFalse(iterator.hasNext());
- }
-
private static void inspect4(CodeInspector inspector) {
MethodSubject main = inspector.clazz("memberrebinding4.Memberrebinding").method(TEST);
Iterator<InvokeInstructionSubject> iterator =
@@ -259,24 +177,18 @@
}
final String name;
- final Frontend kind;
final Backend backend;
final AndroidVersion version;
- final Consumer<CodeInspector> originalInspection;
final Consumer<CodeInspector> processedInspection;
private TestConfiguration(
String name,
- Frontend kind,
Backend backend,
AndroidVersion version,
- Consumer<CodeInspector> originalInspection,
Consumer<CodeInspector> processedInspection) {
this.name = name;
- this.kind = kind;
this.backend = backend;
this.version = version;
- this.originalInspection = originalInspection;
this.processedInspection = processedInspection;
}
@@ -285,16 +197,8 @@
String name,
Backend backend,
AndroidVersion version,
- Consumer<CodeInspector> originalInspection,
Consumer<CodeInspector> processedInspection) {
- if (version == AndroidVersion.PRE_N && backend == Backend.DEX) {
- builder.add(
- new TestConfiguration(
- name, Frontend.DEX, backend, version, originalInspection, processedInspection));
- }
- builder.add(
- new TestConfiguration(
- name, Frontend.JAR, backend, version, originalInspection, processedInspection));
+ builder.add(new TestConfiguration(name, backend, version, processedInspection));
}
public Path getDexPath() {
@@ -328,7 +232,7 @@
}
public String toString() {
- return backend + " " + name + " " + kind;
+ return backend + " " + name;
}
}
@@ -341,28 +245,24 @@
"memberrebinding",
backend,
TestConfiguration.AndroidVersion.PRE_N,
- MemberRebindingTest::inspectOriginalMain,
MemberRebindingTest::inspectMain);
TestConfiguration.add(
builder,
"memberrebinding2",
backend,
TestConfiguration.AndroidVersion.PRE_N,
- MemberRebindingTest::inspectOriginalMain2,
MemberRebindingTest::inspectMain2);
TestConfiguration.add(
builder,
"memberrebinding3",
backend,
TestConfiguration.AndroidVersion.PRE_N,
- MemberRebindingTest::inspectOriginal3,
MemberRebindingTest::inspect3);
TestConfiguration.add(
builder,
"memberrebinding4",
backend,
TestConfiguration.AndroidVersion.N,
- MemberRebindingTest::inspectOriginal4,
MemberRebindingTest::inspect4);
}
return builder.build();
@@ -384,15 +284,8 @@
.collect(Collectors.toList());
}
- if (kind == Frontend.DEX) {
- CodeInspector inspector = new CodeInspector(originalDex);
- originalInspection.accept(inspector);
- }
-
CodeInspector inspector = new CodeInspector(processed);
inspection.accept(inspector);
- // We don't run Art, as the test R8RunExamplesTest already does that.
- // ToolHelper.checkArtOutputIdentical(originalDex, processed, mainClass, null);
}
}
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 087e5d2..cda3c7d 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -37,7 +37,7 @@
protected NamingTestBase(
String test, List<String> keepRulesFiles, BiConsumer<DexItemFactory, NamingLens> inspection) {
- appFileName = ToolHelper.EXAMPLES_BUILD_DIR + test + "/classes.dex";
+ appFileName = ToolHelper.EXAMPLES_BUILD_DIR + test + ".jar";
this.keepRulesFiles = keepRulesFiles;
this.inspection = lens -> inspection.accept(dexItemFactory, lens);
}
diff --git a/src/test/java/com/android/tools/r8/profile/art/dump/DumpArtProfileProvidersTest.java b/src/test/java/com/android/tools/r8/profile/art/dump/DumpArtProfileProvidersTest.java
new file mode 100644
index 0000000..71a58e7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/profile/art/dump/DumpArtProfileProvidersTest.java
@@ -0,0 +1,192 @@
+// 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.profile.art.dump;
+
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.R8FullTestBuilder;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.profile.art.ArtProfileBuilder;
+import com.android.tools.r8.profile.art.ArtProfileProvider;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DumpInputFlags;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.MethodReferenceUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.UTF8TextInputStream;
+import com.android.tools.r8.utils.ZipUtils;
+import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+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 DumpArtProfileProvidersTest extends TestBase {
+
+ private enum DumpStrategy {
+ DIRECTORY,
+ FILE;
+
+ DumpInputFlags createDumpInputFlags(Path dump) {
+ if (this == DIRECTORY) {
+ return DumpInputFlags.dumpToDirectory(dump);
+ }
+ assert this == FILE;
+ return DumpInputFlags.dumpToFile(dump);
+ }
+
+ Path createDumpPath(TemporaryFolder temp) throws IOException {
+ if (this == DIRECTORY) {
+ return temp.newFolder().toPath();
+ }
+ assert this == FILE;
+ return temp.newFile("dump.zip").toPath();
+ }
+ }
+
+ @Parameter(0)
+ public DumpStrategy dumpStrategy;
+
+ @Parameter(1)
+ public TestParameters parameters;
+
+ @Parameters(name = "{1}, {0}")
+ public static List<Object[]> data() {
+ return buildParameters(DumpStrategy.values(), getTestParameters().withNoneRuntime().build());
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path dump = dumpStrategy.createDumpPath(temp);
+ DumpInputFlags dumpInputFlags = dumpStrategy.createDumpInputFlags(dump);
+ try {
+ testForR8(Backend.DEX)
+ .addProgramClasses(Main.class)
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(options -> options.setDumpInputFlags(dumpInputFlags))
+ .allowDiagnosticInfoMessages()
+ .apply(this::addArtProfileProviders)
+ .setMinApi(AndroidApiLevel.LATEST)
+ .compileWithExpectedDiagnostics(
+ diagnostics -> {
+ if (dumpInputFlags.shouldFailCompilation()) {
+ diagnostics.assertErrorsMatch(
+ diagnosticMessage(containsString("Dumped compilation inputs to:")));
+ } else {
+ diagnostics.assertInfosMatch(
+ diagnosticMessage(containsString("Dumped compilation inputs to:")));
+ }
+ });
+ assertFalse("Expected compilation to fail", dumpInputFlags.shouldFailCompilation());
+ } catch (CompilationFailedException e) {
+ assertTrue("Expected compilation to succeed", dumpInputFlags.shouldFailCompilation());
+ }
+ verifyDump(dump);
+ }
+
+ private void addArtProfileProviders(R8FullTestBuilder testBuilder) {
+ testBuilder.addArtProfileForRewriting(
+ new ArtProfileProvider() {
+
+ @Override
+ public void getArtProfile(ArtProfileBuilder profileBuilder) {
+ profileBuilder.addHumanReadableArtProfile(
+ new UTF8TextInputStream(StringUtils.joinLines("# Comment", "Lfoo/Bar;")),
+ parserBuilder -> {});
+ ClassReference bazClassReference = Reference.classFromDescriptor("Lfoo/Baz;");
+ MethodReference bazMainMethodReference =
+ MethodReferenceUtils.mainMethod(bazClassReference);
+ profileBuilder.addClassRule(
+ classRuleBuilder -> classRuleBuilder.setClassReference(bazClassReference));
+ profileBuilder.addMethodRule(
+ methodRuleBuilder ->
+ methodRuleBuilder
+ .setMethodReference(bazMainMethodReference)
+ .setMethodRuleInfo(
+ methodRuleInfoBuilder -> methodRuleInfoBuilder.setIsHot(true)));
+ }
+
+ @Override
+ public Origin getOrigin() {
+ return Origin.unknown();
+ }
+ });
+ testBuilder.addArtProfileForRewriting(
+ new ArtProfileProvider() {
+
+ @Override
+ public void getArtProfile(ArtProfileBuilder profileBuilder) {
+ ClassReference bazClassReference = Reference.classFromDescriptor("Lfoo/Baz;");
+ MethodReference bazMainMethodReference =
+ MethodReferenceUtils.mainMethod(bazClassReference);
+ profileBuilder.addClassRule(
+ classRuleBuilder -> classRuleBuilder.setClassReference(bazClassReference));
+ profileBuilder.addHumanReadableArtProfile(
+ new UTF8TextInputStream(StringUtils.joinLines("# Comment", "Lfoo/Bar;")),
+ parserBuilder -> {});
+ profileBuilder.addMethodRule(
+ methodRuleBuilder ->
+ methodRuleBuilder
+ .setMethodReference(bazMainMethodReference)
+ .setMethodRuleInfo(
+ methodRuleInfoBuilder -> methodRuleInfoBuilder.setIsHot(true)));
+ }
+
+ @Override
+ public Origin getOrigin() {
+ return Origin.unknown();
+ }
+ });
+ }
+
+ private void verifyDump(Path dump) throws IOException {
+ if (dumpStrategy == DumpStrategy.DIRECTORY) {
+ List<Path> dumps =
+ Files.walk(dump, 1).filter(path -> path.toFile().isFile()).collect(Collectors.toList());
+ assertEquals(1, dumps.size());
+ dump = dumps.get(0);
+ }
+
+ assertTrue(Files.exists(dump));
+ Path unzipped = temp.newFolder().toPath();
+ ZipUtils.unzip(dump.toString(), unzipped.toFile());
+
+ Path artProfile1 = unzipped.resolve("art-profile-1.txt");
+ assertTrue(Files.exists(artProfile1));
+ assertEquals(
+ Lists.newArrayList(
+ "# Comment", "Lfoo/Bar;", "Lfoo/Baz;", "HLfoo/Baz;->main([Ljava/lang/String;)V"),
+ FileUtils.readAllLines(artProfile1));
+
+ Path artProfile2 = unzipped.resolve("art-profile-2.txt");
+ assertTrue(Files.exists(artProfile2));
+ assertEquals(
+ Lists.newArrayList(
+ "Lfoo/Baz;", "# Comment", "Lfoo/Bar;", "HLfoo/Baz;->main([Ljava/lang/String;)V"),
+ FileUtils.readAllLines(artProfile2));
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {}
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/regress/Regress37740372.java b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
index 8047716..b46866c 100644
--- a/src/test/java/com/android/tools/r8/regress/Regress37740372.java
+++ b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
@@ -8,12 +8,11 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.D8Command.Builder;
import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.DexIndexedConsumerData;
import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.smali.SmaliTestBase;
@@ -22,7 +21,6 @@
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.Base64;
-import java.util.Set;
import org.junit.Test;
public class Regress37740372 extends SmaliTestBase {
@@ -142,10 +140,9 @@
}
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
- assertEquals(0, fileIndex);
- this.data = data.copyByteData();
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ assertEquals(0, data.getFileIndex());
+ this.data = data.getByteDataCopy();
}
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
index 0c031df..36a00f1 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -68,6 +68,7 @@
import com.android.tools.r8.retrace.stacktraces.OutsideLineRangeStackTraceTest;
import com.android.tools.r8.retrace.stacktraces.OverloadSameLineTest;
import com.android.tools.r8.retrace.stacktraces.OverloadedWithAndWithoutRangeStackTrace;
+import com.android.tools.r8.retrace.stacktraces.PreambleLineNumberStackTrace;
import com.android.tools.r8.retrace.stacktraces.RetraceAssertionErrorStackTrace;
import com.android.tools.r8.retrace.stacktraces.SingleLineNoLineNumberStackTrace;
import com.android.tools.r8.retrace.stacktraces.SourceFileNameSynthesizeStackTrace;
@@ -428,6 +429,11 @@
}
@Test
+ public void testPreambleLineNumberStackTrace() throws Exception {
+ runRetraceTest(new PreambleLineNumberStackTrace());
+ }
+
+ @Test
public void testMapVersionWarningStackTrace() throws Exception {
// TODO(b/204289928): Internalize the diagnostics checking.
assumeFalse(external);
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java
new file mode 100644
index 0000000..316fdfc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java
@@ -0,0 +1,59 @@
+// 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.stacktraces;
+
+import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class PreambleLineNumberStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ " at kotlin.t.a(SourceFile)",
+ " at kotlin.t.a(SourceFile:0)",
+ " at kotlin.t.a(SourceFile:1)",
+ " at kotlin.t.a(SourceFile:2)");
+ }
+
+ @Override
+ public String mapping() {
+ return StringUtils.lines(
+ "kotlin.ResultKt -> kotlin.t:",
+ " 1:1:void createFailure(java.lang.Throwable):122:122 -> a",
+ " 2:2:void createFailure(java.lang.Throwable):124:124 -> a");
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ " at kotlin.ResultKt.createFailure(Result.kt)",
+ // TODO(b/270593835): We should report kotlin.ResultKt.createFailure(Result.kt).
+ " at kotlin.ResultKt.a(Result.kt:0)",
+ " at kotlin.ResultKt.createFailure(Result.kt:122)",
+ " at kotlin.ResultKt.createFailure(Result.kt:124)");
+ }
+
+ @Override
+ public List<String> retraceVerboseStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ // TODO(b/270593835): We should not have an ambiguous frame reporting here.
+ " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:122)",
+ " <OR> at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:124)",
+ // TODO(b/270593835): We should report kotlin.ResultKt.createFailure(Result.kt).
+ " at kotlin.ResultKt.a(Result.kt:0)",
+ " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:122)",
+ " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:124)");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java b/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java
index c67394a..3d3ed7f 100644
--- a/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java
@@ -87,6 +87,7 @@
case V7_0_0:
case V13_0_0:
+ case V14_0_0:
return StringUtils.joinLines(
"Hello!",
"Unexpected outcome of checkcast",
diff --git a/src/test/java/com/android/tools/r8/shaking/R8Shaking2LookupTest.java b/src/test/java/com/android/tools/r8/shaking/R8Shaking2LookupTest.java
index 63e5bc9..ef19e65 100644
--- a/src/test/java/com/android/tools/r8/shaking/R8Shaking2LookupTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/R8Shaking2LookupTest.java
@@ -22,7 +22,6 @@
public class R8Shaking2LookupTest {
- static final String APP_FILE_NAME = ToolHelper.EXAMPLES_BUILD_DIR + "shaking2/classes.dex";
private DirectMappedDexApplication program;
private DexItemFactory dexItemFactory;
private AppInfoWithClassHierarchy appInfo;
@@ -30,7 +29,9 @@
@Before
public void readApp() throws IOException, ExecutionException {
- program = ToolHelper.buildApplication(ImmutableList.of(APP_FILE_NAME));
+ program =
+ ToolHelper.buildApplication(
+ ImmutableList.of(ToolHelper.EXAMPLES_BUILD_DIR + "shaking2.jar"));
dexItemFactory = program.dexItemFactory;
AppView<AppInfoWithClassHierarchy> appView = AppView.createForR8(program);
appInfo = appView.appInfo();
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 0bc240e..223140b 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
@@ -60,10 +60,7 @@
// Generate R8 processed version without library option.
String test = "shaking2";
testForR8(backend)
- .applyIf(
- backend.isCf(),
- builder -> builder.addProgramFiles(getProgramFiles(test)),
- builder -> builder.addProgramDexFileData(getProgramDexFileData(test)))
+ .addProgramFiles(getProgramFiles(test))
.addKeepRuleFiles(Paths.get(EXAMPLES_DIR, test, "keep-rules.txt"))
.addIgnoreWarnings()
.setMinApi(minApi)
@@ -75,10 +72,7 @@
// Generate R8 processed version without library option.
String test = "shaking2";
testForR8(backend)
- .applyIf(
- backend.isCf(),
- builder -> builder.addProgramFiles(getProgramFiles(test)),
- builder -> builder.addProgramDexFileData(getProgramDexFileData(test)))
+ .addProgramFiles(getProgramFiles(test))
.addLibraryFiles()
.addKeepRuleFiles(Paths.get(EXAMPLES_DIR, test, "keep-rules.txt"))
.allowDiagnosticErrorMessages()
@@ -107,10 +101,7 @@
// Generate R8 processed version without library option.
String test = "shaking1";
testForR8(backend)
- .applyIf(
- backend.isCf(),
- builder -> builder.addProgramFiles(getProgramFiles(test)),
- builder -> builder.addProgramDexFileData(getProgramDexFileData(test)))
+ .addProgramFiles(getProgramFiles(test))
.addKeepRuleFiles(Paths.get(EXAMPLES_DIR, test, "keep-rules.txt"))
.addOptionsModification(options -> options.inlinerOptions().enableInlining = false)
.setMinApi(minApi)
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
index bbc5b5b..b390f85 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;
-import static org.junit.Assume.assumeFalse;
-
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
@@ -25,7 +23,6 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
@@ -48,36 +45,22 @@
*/
public abstract class TreeShakingTest extends TestBase {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> defaultTreeShakingParameters() {
- return data(Frontend.values(), MinifyMode.values());
+ return data(MinifyMode.values());
}
public static List<Object[]> data(MinifyMode[] minifyModes) {
- return data(Frontend.values(), minifyModes);
- }
-
- public static List<Object[]> data(Frontend[] frontends, MinifyMode[] minifyModes) {
- return buildParameters(
- frontends, getTestParameters().withAllRuntimesAndApiLevels().build(), minifyModes);
+ return buildParameters(getTestParameters().withAllRuntimesAndApiLevels().build(), minifyModes);
}
protected abstract String getName();
protected abstract String getMainClass();
- protected enum Frontend {
- DEX, JAR
- }
-
- private final Frontend frontend;
private final TestParameters parameters;
private final MinifyMode minify;
- public Frontend getFrontend() {
- return frontend;
- }
-
public TestParameters getParameters() {
return parameters;
}
@@ -86,8 +69,7 @@
return minify;
}
- public TreeShakingTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- this.frontend = frontend;
+ public TreeShakingTest(TestParameters parameters, MinifyMode minify) {
this.parameters = parameters;
this.minify = minify;
}
@@ -173,10 +155,9 @@
ThrowableConsumer<R8FullTestBuilder> testBuilderConsumer,
DiagnosticsConsumer diagnosticsConsumer)
throws Exception {
- assumeFalse(frontend == Frontend.DEX && parameters.isCfRuntime());
- String originalDex = ToolHelper.TESTS_BUILD_DIR + getName() + "/classes.dex";
- String programFile =
- frontend == Frontend.DEX ? originalDex : ToolHelper.TESTS_BUILD_DIR + getName() + ".jar";
+
+ String programFile = ToolHelper.TESTS_BUILD_DIR + getName() + ".jar";
+
R8FullTestBuilder testBuilder =
testForR8(parameters.getBackend())
// Go through app builder to add dex files.
@@ -226,36 +207,43 @@
if (!ToolHelper.artSupported() && !ToolHelper.compareAgaintsGoldenFiles()) {
return;
}
- Consumer<ArtCommandBuilder> extraArtArgs = builder -> {
- builder.appendClasspath(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib/classes.dex");
- };
+ Path shakingLib =
+ testForD8(Backend.DEX)
+ .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib.jar"))
+ .setMinApi(parameters)
+ .compile()
+ .writeToZip();
+ Consumer<ArtCommandBuilder> extraArtArgs =
+ builder -> {
+ builder.appendClasspath(shakingLib.toString());
+ };
+ String d8Output =
+ testForD8(Backend.DEX)
+ .setMinApi(parameters)
+ .addProgramFiles(Paths.get(programFile))
+ .compile()
+ .writeToZip()
+ .toString();
DexVm dexVm = parameters.getRuntime().asDex().getVm();
- if (Files.exists(Paths.get(originalDex))) {
- if (outputComparator != null) {
- String output1 =
- ToolHelper.runArtNoVerificationErrors(
- Collections.singletonList(originalDex), getMainClass(), extraArtArgs, dexVm);
- String output2 =
- ToolHelper.runArtNoVerificationErrors(
- Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
- outputComparator.accept(output1, output2);
- } else {
- ToolHelper.checkArtOutputIdentical(
- Collections.singletonList(originalDex),
- Collections.singletonList(outJar.toString()),
- getMainClass(),
- extraArtArgs,
- null);
- }
- if (dexComparator != null) {
- CodeInspector ref = new CodeInspector(Paths.get(originalDex));
- dexComparator.accept(ref, compileResult.inspector());
- }
+ if (outputComparator != null) {
+ String output1 =
+ ToolHelper.runArtNoVerificationErrors(
+ Collections.singletonList(d8Output), getMainClass(), extraArtArgs, dexVm);
+ String output2 =
+ ToolHelper.runArtNoVerificationErrors(
+ Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
+ outputComparator.accept(output1, output2);
} else {
- Assert.assertNull(outputComparator);
- Assert.assertNull(dexComparator);
- ToolHelper.runArtNoVerificationErrors(
- Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
+ ToolHelper.checkArtOutputIdentical(
+ Collections.singletonList(d8Output),
+ Collections.singletonList(outJar.toString()),
+ getMainClass(),
+ extraArtArgs,
+ null);
+ }
+ if (dexComparator != null) {
+ CodeInspector ref = new CodeInspector(Paths.get(d8Output));
+ dexComparator.accept(ref, compileResult.inspector());
}
if (inspection != null) {
compileResult.inspect(inspection);
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java
index c20ebb6..a49e547 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java
@@ -15,13 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShaking10Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking10Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking10Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java
index 47b696d..9be0804 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking11Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking11Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking11Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java
index 15e18bd..c59cedc 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java
@@ -24,10 +24,9 @@
@RunWith(Parameterized.class)
public class TreeShaking12Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return buildParameters(
- Frontend.values(),
getTestParameters()
.withAllRuntimes()
.withApiLevelsStartingAtIncluding(AndroidApiLevel.K)
@@ -35,8 +34,8 @@
MinifyMode.values());
}
- public TreeShaking12Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking12Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java
index 7cf7921..4e33394 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java
@@ -22,13 +22,13 @@
@RunWith(Parameterized.class)
public class TreeShaking13Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking13Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking13Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java
index 36b3b37..4733d3c 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking14Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking14Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking14Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
index 34da969..dcf64e5 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
@@ -23,13 +23,13 @@
@RunWith(Parameterized.class)
public class TreeShaking15Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return data(MinifyMode.withoutNone());
}
- public TreeShaking15Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking15Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java
index 785e505..6d0136b 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java
@@ -15,13 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShaking16Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return data(MinifyMode.withoutNone());
}
- public TreeShaking16Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking16Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
index e2b7095..aa8ed3d 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
@@ -19,13 +19,13 @@
@RunWith(Parameterized.class)
public class TreeShaking17Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking17Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking17Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
index d91a2fd..eb255b8 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking18Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking18Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking18Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java
index e5f45bb..5b4b206 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java
@@ -22,13 +22,13 @@
@RunWith(Parameterized.class)
public class TreeShaking19Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking19Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking19Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java
index ad658b9..1ef98a64 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java
@@ -21,13 +21,13 @@
@RunWith(Parameterized.class)
public class TreeShaking1Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{2}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking1Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking1Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
index 74232e1..d436691 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
@@ -22,13 +22,13 @@
@RunWith(Parameterized.class)
public class TreeShaking2Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking2Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking2Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java
index 38cee4e..57ef8e6 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking3Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking3Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking3Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java
index abf9be6..b5c6e81 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java
@@ -15,13 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShaking4Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking4Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking4Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java
index cca8f8b..a7c07b8 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking5Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking5Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking5Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java
index 7a91541..360394b 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java
@@ -19,13 +19,13 @@
@RunWith(Parameterized.class)
public class TreeShaking6Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking6Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking6Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java
index 8a6cf36..991e93c 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking7Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking7Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking7Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java
index 9da3d01..0fe177f 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java
@@ -22,13 +22,13 @@
@RunWith(Parameterized.class)
public class TreeShaking8Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking8Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking8Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java
index ec8c6ad..0b89761 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java
@@ -18,13 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShaking9Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShaking9Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShaking9Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java
index 0c65f06..b9ba7b5 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java
@@ -15,13 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAndroidNTest extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
- return data(new Frontend[] {Frontend.JAR}, MinifyMode.values());
+ return data(MinifyMode.values());
}
- public TreeShakingAndroidNTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAndroidNTest(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java
index 728aa09..73c2026 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java
@@ -18,14 +18,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAnnotationremovalTest extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAnnotationremovalTest(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAnnotationremovalTest(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java
index 1aa50e1..42c3096 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumenosideeffects1Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumenosideeffects1Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumenosideeffects1Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java
index a57e98f..cb141fb 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java
@@ -19,14 +19,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumenosideeffects2Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumenosideeffects2Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumenosideeffects2Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java
index b83e0b9..ac17be8 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumenosideeffects3Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumenosideeffects3Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumenosideeffects3Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java
index 56083fc..4b5a370 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumenosideeffects4Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "mode:{0}minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumenosideeffects4Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumenosideeffects4Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java
index fa138dd..6fe0e05 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumenosideeffects5Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumenosideeffects5Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumenosideeffects5Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java
index 172c64d..1948663 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumenosideeffects6Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumenosideeffects6Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumenosideeffects6Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java
index 45511b7..ac1338c 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues1Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues1Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues1Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java
index 88ca339..2dd0cc6 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues2Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues2Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues2Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java
index 5237778..f80b2f8 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues3Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues3Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues3Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java
index 4790850..6b1d691 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues4Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues4Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues4Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java
index 9304ed8..8ee9a97 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java
@@ -17,14 +17,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues5Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues5Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues5Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java
index 59c535d..882a3e4 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java
@@ -20,14 +20,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues6Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues6Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues6Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java
index c6ca232..f61dbd7 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java
@@ -20,14 +20,13 @@
@RunWith(Parameterized.class)
public class TreeShakingAssumevalues7Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues7Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingAssumevalues7Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java
index 08dfc6a..4ab4fc9 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java
@@ -16,13 +16,13 @@
@RunWith(Parameterized.class)
public class TreeShakingInliningTest extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingInliningTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingInliningTest(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java
index 95a0876..358de99 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java
@@ -15,14 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShakingMemberrebinding2Test extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingMemberrebinding2Test(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingMemberrebinding2Test(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java
index b8151d6..1873c13 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java
@@ -16,14 +16,13 @@
@RunWith(Parameterized.class)
public class TreeShakingMinificationTest extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return defaultTreeShakingParameters();
}
- public TreeShakingMinificationTest(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingMinificationTest(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java
index 7223763..6d424bd 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java
@@ -15,14 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShakingMinifygenericTest extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return data(MinifyMode.withoutNone());
}
- public TreeShakingMinifygenericTest(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingMinifygenericTest(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java
index 968ef92..3763114a 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java
@@ -15,14 +15,13 @@
@RunWith(Parameterized.class)
public class TreeShakingMinifygenericwithinnerTest extends TreeShakingTest {
- @Parameters(name = "mode:{0}-{1} minify:{2}")
+ @Parameters(name = "{0} minify:{1}")
public static List<Object[]> data() {
return data(MinifyMode.withoutNone());
}
- public TreeShakingMinifygenericwithinnerTest(
- Frontend frontend, TestParameters parameters, MinifyMode minify) {
- super(frontend, parameters, minify);
+ public TreeShakingMinifygenericwithinnerTest(TestParameters parameters, MinifyMode minify) {
+ super(parameters, minify);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnosticTest.java b/src/test/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnosticTest.java
index f4bb9ec..d9ed155 100644
--- a/src/test/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnosticTest.java
+++ b/src/test/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnosticTest.java
@@ -46,7 +46,6 @@
.addProgramClasses(Main.class)
.addStartupProfileProviders(getStartupProfileProviders())
.release()
- .setIntermediate(true)
.setMinApi(AndroidApiLevel.LATEST)
.compileWithExpectedDiagnostics(this::inspectDiagnostics);
}
diff --git a/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java
new file mode 100644
index 0000000..e273552
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java
@@ -0,0 +1,208 @@
+// 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.synthesis;
+
+import static com.android.tools.r8.synthesis.SyntheticItemsTestUtils.syntheticBackportClass;
+import static com.android.tools.r8.synthesis.SyntheticItemsTestUtils.syntheticLambdaClass;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.ClassFileConsumerData;
+import com.android.tools.r8.DesugarGraphConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanBox;
+import com.google.common.collect.ImmutableSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RepeatedCompilationNestedSyntheticsTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final Backend intermediateBackend;
+
+ @Parameterized.Parameters(name = "{0}, intermediate: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultDexRuntime().withMinimumApiLevel().build(),
+ Backend.values());
+ }
+
+ public RepeatedCompilationNestedSyntheticsTest(
+ TestParameters parameters, Backend intermediateBackend) {
+ this.parameters = parameters;
+ this.intermediateBackend = intermediateBackend;
+ }
+
+ @Test
+ public void test() throws Exception {
+ assertEquals(Backend.DEX, parameters.getBackend());
+
+ ClassReference syntheticLambdaClass = syntheticLambdaClass(UsesBackport.class, 0);
+ ImmutableSet<String> expectedClassOutputs =
+ ImmutableSet.of(descriptor(UsesBackport.class), syntheticLambdaClass.getDescriptor());
+
+ Map<String, byte[]> firstCompilation = new HashMap<>();
+ testForD8(Backend.CF)
+ // High API level such that only the lambda is desugared.
+ .setMinApi(AndroidApiLevel.S)
+ .setIntermediate(true)
+ .addClasspathClasses(I.class)
+ .addProgramClasses(UsesBackport.class)
+ .setProgramConsumer(
+ new ClassFileConsumer() {
+ @Override
+ public void acceptClassFile(ClassFileConsumerData data) {
+ firstCompilation.put(data.getClassDescriptor(), data.getByteDataCopy());
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ })
+ .compile();
+ assertEquals(expectedClassOutputs, firstCompilation.keySet());
+
+ Map<String, byte[]> secondCompilation = new HashMap<>();
+ ImmutableSet.Builder<String> allDescriptors = ImmutableSet.builder();
+ BooleanBox matched = new BooleanBox(false);
+ for (Entry<String, byte[]> entry : firstCompilation.entrySet()) {
+ byte[] bytes = entry.getValue();
+ Origin origin =
+ new Origin(Origin.root()) {
+ @Override
+ public String part() {
+ return entry.getKey();
+ }
+ };
+ testForD8(intermediateBackend)
+ .setMinApi(parameters)
+ .setIntermediate(true)
+ .addClasspathClasses(I.class)
+ .apply(b -> b.getBuilder().addClassProgramData(bytes, origin))
+ .apply(
+ b ->
+ b.getBuilder()
+ .setDesugarGraphConsumer(
+ new DesugarGraphConsumer() {
+
+ @Override
+ public void accept(Origin dependent, Origin dependency) {
+ assertThat(
+ dependency.toString(), containsString(binaryName(I.class)));
+ assertThat(
+ dependent.toString(),
+ containsString(syntheticLambdaClass.getBinaryName()));
+ matched.set(true);
+ }
+
+ @Override
+ public void finished() {}
+ }))
+ .applyIf(
+ intermediateBackend == Backend.CF,
+ b ->
+ b.setProgramConsumer(
+ new ClassFileConsumer() {
+ @Override
+ public void acceptClassFile(ClassFileConsumerData data) {
+ secondCompilation.put(data.getClassDescriptor(), data.getByteDataCopy());
+ allDescriptors.add(data.getClassDescriptor());
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ }),
+ b ->
+ b.setProgramConsumer(
+ new DexFilePerClassFileConsumer() {
+ @Override
+ public synchronized void acceptDexFile(
+ DexFilePerClassFileConsumerData data) {
+ secondCompilation.put(
+ data.getPrimaryClassDescriptor(), data.getByteDataCopy());
+ allDescriptors.addAll(data.getClassDescriptors());
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ }))
+ .compile();
+ }
+ assertTrue(matched.get());
+ // The dex file per class file output should maintain the exact same set of primary descriptors.
+ if (intermediateBackend == Backend.DEX) {
+ assertEquals(expectedClassOutputs, secondCompilation.keySet());
+ }
+ // The total set of classes should also include the backport. The backport should be
+ // hygienically placed under the synthetic lambda (not the context of the lambda!).
+ assertEquals(
+ ImmutableSet.<String>builder()
+ .addAll(expectedClassOutputs)
+ .add(syntheticBackportClass(syntheticLambdaClass, 0).getDescriptor())
+ .build(),
+ allDescriptors.build());
+
+ testForD8(Backend.DEX)
+ .setMinApi(parameters)
+ .addProgramClasses(I.class, TestClass.class)
+ .applyIf(
+ intermediateBackend == Backend.CF,
+ b -> b.addProgramClassFileData(secondCompilation.values()),
+ b -> b.addProgramDexFileData(secondCompilation.values()))
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("1")
+ .inspect(
+ inspector -> {
+ Set<String> descriptors =
+ inspector.allClasses().stream()
+ .map(c -> c.getFinalReference().getDescriptor())
+ .collect(Collectors.toSet());
+ assertEquals(
+ ImmutableSet.of(
+ descriptor(I.class),
+ descriptor(TestClass.class),
+ descriptor(UsesBackport.class),
+ // The merge step will reestablish the original contexts, thus both the lambda
+ // and the backport are placed under the non-synthetic input class
+ // UsesBackport.
+ syntheticBackportClass(UsesBackport.class, 0).getDescriptor(),
+ syntheticLambdaClass(UsesBackport.class, 1).getDescriptor()),
+ descriptors);
+ });
+ }
+
+ interface I {
+ int compare(boolean b1, boolean b2);
+ }
+
+ static class UsesBackport {
+ public static I foo() {
+ return Boolean::compare;
+ }
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println(UsesBackport.foo().compare(true, false));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java
new file mode 100644
index 0000000..842c56e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java
@@ -0,0 +1,166 @@
+// 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.synthesis;
+
+import static com.android.tools.r8.synthesis.SyntheticItemsTestUtils.syntheticBackportClass;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumerData;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RepeatedCompilationSyntheticsTest extends TestBase {
+
+ private final String EXPECTED = StringUtils.lines("-2", "254");
+
+ private final TestParameters parameters;
+ private final Backend intermediateBackend;
+
+ private final AndroidApiLevel API_WITH_BYTE_COMPARE = AndroidApiLevel.K;
+
+ @Parameterized.Parameters(name = "{0}, intermediate: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultDexRuntime().withMinimumApiLevel().build(),
+ Backend.values());
+ }
+
+ public RepeatedCompilationSyntheticsTest(TestParameters parameters, Backend intermediateBackend) {
+ this.parameters = parameters;
+ this.intermediateBackend = intermediateBackend;
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ testForD8(parameters.getBackend())
+ .addProgramClasses(TestClass.class)
+ .addProgramClassFileData(getTransformedUsesBackport())
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void test() throws Exception {
+ assertEquals(Backend.DEX, parameters.getBackend());
+
+ Map<String, byte[]> firstCompilation = new HashMap<>();
+ testForD8(Backend.CF)
+ // High API level such that only the compareUnsigned is desugared.
+ .setMinApi(API_WITH_BYTE_COMPARE)
+ .setIntermediate(true)
+ .addProgramClassFileData(getTransformedUsesBackport())
+ .setProgramConsumer(
+ new ClassFileConsumer() {
+ @Override
+ public synchronized void accept(
+ ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ byte[] old = firstCompilation.put(descriptor, data.copyByteData());
+ assertNull("Duplicate " + descriptor, old);
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ })
+ .compile();
+ assertEquals(
+ ImmutableSet.of(
+ descriptor(UsesBackport.class),
+ syntheticBackportClass(UsesBackport.class, 0).getDescriptor()),
+ firstCompilation.keySet());
+
+ List<String> secondCompilation = new ArrayList<>();
+ for (Entry<String, byte[]> entry : firstCompilation.entrySet()) {
+ byte[] bytes = entry.getValue();
+ testForD8(intermediateBackend)
+ .setMinApi(parameters)
+ .setIntermediate(true)
+ .addProgramClassFileData(bytes)
+ .applyIf(
+ intermediateBackend == Backend.CF,
+ b ->
+ b.setProgramConsumer(
+ new ClassFileConsumer() {
+ @Override
+ public synchronized void accept(
+ ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ secondCompilation.add(descriptor);
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ }),
+ b ->
+ b.setProgramConsumer(
+ new DexFilePerClassFileConsumer() {
+ @Override
+ public synchronized void acceptDexFile(
+ DexFilePerClassFileConsumerData data) {
+ secondCompilation.addAll(data.getClassDescriptors());
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ }))
+ .compile();
+ }
+
+ // TODO(b/271235788): The repeated compilation is unsound and we have duplicate definitions of
+ // the backports both using the same type name.
+ secondCompilation.sort(String::compareTo);
+ assertEquals(
+ ImmutableList.of(
+ syntheticBackportClass(UsesBackport.class, 0).getDescriptor(),
+ syntheticBackportClass(UsesBackport.class, 0).getDescriptor(),
+ descriptor(UsesBackport.class)),
+ secondCompilation);
+ }
+
+ private byte[] getTransformedUsesBackport() throws Exception {
+ return transformer(UsesBackport.class)
+ .transformMethodInsnInMethod(
+ "bar",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ assertEquals("compare", name);
+ visitor.visitMethodInsn(opcode, owner, "compareUnsigned", descriptor, isInterface);
+ })
+ .transform();
+ }
+
+ static class UsesBackport {
+ public static int foo(byte[] bs) {
+ return Byte.compare(bs[0], bs[1]);
+ }
+
+ public static int bar(byte[] bs) {
+ return Byte.compare /*Unsigned*/(bs[0], bs[1]);
+ }
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println(UsesBackport.foo(new byte[] {-1, 1}));
+ System.out.println(UsesBackport.bar(new byte[] {-1, 1}));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java
index 4321812..4190da5 100644
--- a/src/test/java/com/android/tools/r8/utils/Smali.java
+++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
-import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DexIndexedConsumerData;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.ApplicationWriter;
@@ -19,7 +19,6 @@
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import org.antlr.runtime.CommonTokenStream;
@@ -129,9 +128,8 @@
byte[] contents;
@Override
- public void accept(
- int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {
- contents = data.copyByteData();
+ public void acceptDexIndexedFile(DexIndexedConsumerData data) {
+ contents = data.getByteDataCopy();
}
@Override
diff --git a/third_party/android_jar/libcore_latest.tar.gz.sha1 b/third_party/android_jar/libcore_latest.tar.gz.sha1
index c300639..a4bef52 100644
--- a/third_party/android_jar/libcore_latest.tar.gz.sha1
+++ b/third_party/android_jar/libcore_latest.tar.gz.sha1
@@ -1 +1 @@
-f7570bec27977e786b637241778e6cfdadf25f7f
\ No newline at end of file
+a82e05e08874d8b869d7f614c24ef8981888c702
\ No newline at end of file
diff --git a/third_party/gradle/gradle-8.0.tar.gz.sha1 b/third_party/gradle/gradle-8.0.tar.gz.sha1
new file mode 100644
index 0000000..d67ee97
--- /dev/null
+++ b/third_party/gradle/gradle-8.0.tar.gz.sha1
@@ -0,0 +1 @@
+dd1f4697d211954afb3034214453c2e06769a036
\ No newline at end of file
diff --git a/tools/compiledump.py b/tools/compiledump.py
index 12c8288..c313cb9 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -199,6 +199,16 @@
def main_dex_rules_resource(self):
return self.if_exists('main-dex-rules.txt')
+ def art_profile_resources(self):
+ art_profile_resources = []
+ while True:
+ current_art_profile_index = len(art_profile_resources) + 1
+ art_profile_resource = self.if_exists(
+ 'art-profile-%s.txt' % current_art_profile_index)
+ if art_profile_resource is None:
+ return art_profile_resources
+ art_profile_resources.append(art_profile_resource)
+
def startup_profile_resources(self):
startup_profile_resources = []
while True:
@@ -252,6 +262,8 @@
if stripped:
pair = stripped.split('=')
build_properties[pair[0]] = pair[1]
+ if 'mode' not in build_properties:
+ build_properties['mode'] = 'release'
return build_properties
def determine_version(args, dump):
@@ -260,21 +272,33 @@
return args.version
def determine_compiler(args, build_properties):
- compilers = ['d8', 'r8', 'r8full', 'l8', 'l8d8']
+ compilers = ['d8', 'r8', 'r8full', 'l8', 'l8d8', 'tracereferences']
compiler = args.compiler
if not compiler and 'tool' in build_properties:
compiler = build_properties.get('tool').lower()
- if (compiler == 'r8'):
+ if compiler == 'r8':
if not 'force-proguard-compatibility' in build_properties:
error("Unable to determine R8 compiler variant from build.properties."
" No value for 'force-proguard-compatibility'.")
if build_properties.get('force-proguard-compatibility').lower() == 'false':
compiler = compiler + 'full'
+ if compiler == 'TraceReferences':
+ compiler = build_properties.get('tool').lower()
if compiler not in compilers:
error("Unable to determine a compiler to use. Specified %s,"
" Valid options: %s" % (args.compiler, ', '.join(compilers)))
return compiler
+def determine_trace_references_commands(build_properties, output):
+ trace_ref_consumer = build_properties.get('trace_references_consumer')
+ if trace_ref_consumer == 'com.android.tools.r8.tracereferences.TraceReferencesCheckConsumer':
+ return ["--check"]
+ else:
+ assert trace_ref_consumer == 'com.android.tools.r8.tracereferences.TraceReferencesKeepRules'
+ args = ['--allowobfuscation'] if build_properties.get('minification') == 'true' else []
+ args.extend(['--keep-rules', '--output', output])
+ return args
+
def is_l8_compiler(compiler):
return compiler.startswith('l8')
@@ -304,6 +328,9 @@
return build_properties.get('min-api')
return None
+def determine_residual_art_profile_output(art_profile, temp):
+ return os.path.join(temp, os.path.basename(art_profile)[:-4] + ".out.txt")
+
def determine_desugared_lib_pg_conf_output(temp):
return os.path.join(temp, 'desugared-library-keep-rules.config')
@@ -400,7 +427,7 @@
return False
def prepare_r8_wrapper(dist, temp, jdkhome):
- compile_with_javac(
+ compile_wrapper_with_javac(
dist,
temp,
jdkhome,
@@ -409,7 +436,7 @@
'src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java'))
def prepare_d8_wrapper(dist, temp, jdkhome):
- compile_with_javac(
+ compile_wrapper_with_javac(
dist,
temp,
jdkhome,
@@ -417,10 +444,14 @@
utils.REPO_ROOT,
'src/main/java/com/android/tools/r8/utils/CompileDumpD8.java'))
-def compile_with_javac(dist, temp, jdkhome, path):
+def compile_wrapper_with_javac(dist, temp, jdkhome, path):
+ base_path = os.path.join(
+ utils.REPO_ROOT,
+ 'src/main/java/com/android/tools/r8/utils/CompileDumpBase.java')
cmd = [
jdk.GetJavacExecutable(jdkhome),
path,
+ base_path,
'-d', temp,
'-cp', dist,
]
@@ -478,7 +509,7 @@
if args.r8_flags:
cmd.extend(args.r8_flags.split(' '))
if hasattr(args, 'properties'):
- cmd.extend(args.properties);
+ cmd.extend(args.properties)
cmd.extend(determine_properties(build_properties))
cmd.extend(['-cp', '%s:%s' % (temp, jar)])
if compiler == 'd8':
@@ -486,25 +517,33 @@
cmd.append('com.android.tools.r8.utils.CompileDumpD8')
if is_l8_compiler(compiler):
cmd.append('com.android.tools.r8.L8')
+ if compiler == 'tracereferences':
+ cmd.append('com.android.tools.r8.tracereferences.TraceReferences')
+ cmd.extend(determine_trace_references_commands(build_properties, out))
if compiler.startswith('r8'):
prepare_r8_wrapper(jar, temp, jdkhome)
cmd.append('com.android.tools.r8.utils.CompileDumpCompatR8')
if compiler == 'r8':
cmd.append('--compat')
- if mode == 'debug':
- cmd.append('--debug')
- else:
- cmd.append('--release')
+ if compiler != 'tracereferences':
+ assert mode == 'debug' or mode == 'release'
+ cmd.append('--' + mode)
# For recompilation of dumps run_on_app_dumps pass in a program jar.
- cmd.append(determine_program_jar(args, dump))
- cmd.extend(['--output', out])
+ program_jar = determine_program_jar(args, dump)
+ if compiler != 'tracereferences':
+ cmd.append(program_jar)
+ cmd.extend(['--output', out])
+ else:
+ cmd.extend(['--source', program_jar])
for feature_jar in dump.feature_jars():
cmd.extend(['--feature-jar', feature_jar,
determine_feature_output(feature_jar, temp)])
if dump.library_jar():
cmd.extend(['--lib', dump.library_jar()])
if dump.classpath_jar() and not is_l8_compiler(compiler):
- cmd.extend(['--classpath', dump.classpath_jar()])
+ cmd.extend(
+ ['--target' if compiler == 'tracereferences' else '--classpath',
+ dump.classpath_jar()])
if dump.desugared_library_json() and not args.disable_desugared_lib:
cmd.extend(['--desugared-lib', dump.desugared_library_json()])
if not is_l8_compiler(compiler):
@@ -525,6 +564,11 @@
cmd.extend(['--main-dex-list', dump.main_dex_list_resource()])
if dump.main_dex_rules_resource():
cmd.extend(['--main-dex-rules', dump.main_dex_rules_resource()])
+ for art_profile_resource in dump.art_profile_resources():
+ residual_art_profile_output = \
+ determine_residual_art_profile_output(art_profile_resource, temp)
+ cmd.extend([
+ '--art-profile', art_profile_resource, residual_art_profile_output])
for startup_profile_resource in dump.startup_profile_resources():
cmd.extend(['--startup-profile', startup_profile_resource])
if min_api:
diff --git a/tools/gradle.py b/tools/gradle.py
index 92503a7..5e08468 100755
--- a/tools/gradle.py
+++ b/tools/gradle.py
@@ -17,18 +17,25 @@
GRADLE_DIR = os.path.join(utils.REPO_ROOT, 'third_party', 'gradle')
GRADLE_SHA1 = os.path.join(GRADLE_DIR, 'gradle.tar.gz.sha1')
+GRADLE8_SHA1 = os.path.join(GRADLE_DIR, 'gradle-8.0.tar.gz.sha1')
GRADLE_TGZ = os.path.join(GRADLE_DIR, 'gradle.tar.gz')
+GRADLE8_TGZ = os.path.join(GRADLE_DIR, 'gradle-8.0.tar.gz')
-if utils.IsWindows():
- GRADLE = os.path.join(GRADLE_DIR, 'gradle', 'bin', 'gradle.bat')
-else:
- GRADLE = os.path.join(GRADLE_DIR, 'gradle', 'bin', 'gradle')
+def get_gradle(new_gradle):
+ gradle_dir = 'gradle-8.0' if new_gradle else 'gradle'
+ if utils.IsWindows():
+ return os.path.join(GRADLE_DIR, gradle_dir, 'bin', 'gradle.bat')
+ else:
+ return os.path.join(GRADLE_DIR, gradle_dir, 'bin', 'gradle')
def ParseOptions():
parser = argparse.ArgumentParser(description = 'Call gradle.')
parser.add_argument('--exclude-deps', '--exclude_deps',
help='Build without internalized dependencies.',
default=False, action='store_true')
+ parser.add_argument('--new-gradle', '--new_gradle',
+ help='Run with new experimental gradle configuration',
+ default=False, action='store_true')
parser.add_argument('--no-internal', '--no_internal',
help='Do not build with support for Google internal tests.',
default=False, action='store_true')
@@ -56,7 +63,9 @@
def EnsureGradle():
utils.EnsureDepFromGoogleCloudStorage(
- GRADLE, GRADLE_TGZ, GRADLE_SHA1, 'Gradle binary')
+ get_gradle(False), GRADLE_TGZ, GRADLE_SHA1, 'Gradle binary')
+ utils.EnsureDepFromGoogleCloudStorage(
+ get_gradle(True), GRADLE8_TGZ, GRADLE8_SHA1, 'Gradle binary')
def EnsureJdk():
jdkRoot = jdk.GetJdkRoot()
@@ -68,9 +77,12 @@
EnsureGradle()
EnsureJdk()
-def RunGradleIn(gradleCmd, args, cwd, throw_on_failure=True, env=None):
+def RunGradleIn(
+ gradleCmd, args, cwd, throw_on_failure=True, env=None, new_gradle=False):
EnsureDeps()
cmd = [gradleCmd]
+ args.append(
+ '-c=d8_r8/settings.gradle.kts' if new_gradle else '-b=build.gradle')
cmd.extend(args)
utils.PrintCmd(cmd)
with utils.ChangedWorkingDirectory(cwd):
@@ -82,8 +94,14 @@
def RunGradleWrapperIn(args, cwd, throw_on_failure=True, env=None):
return RunGradleIn('./gradlew', args, cwd, throw_on_failure, env=env)
-def RunGradle(args, throw_on_failure=True, env=None):
- return RunGradleIn(GRADLE, args, utils.REPO_ROOT, throw_on_failure, env=env)
+def RunGradle(args, throw_on_failure=True, env=None, new_gradle=False):
+ return RunGradleIn(
+ get_gradle(new_gradle),
+ args,
+ utils.REPO_ROOT,
+ throw_on_failure,
+ env=env,
+ new_gradle=new_gradle)
def RunGradleExcludeDeps(args, throw_on_failure=True, env=None):
EnsureDeps()
@@ -101,8 +119,12 @@
def RunGradleWrapperInGetOutput(args, cwd, env=None):
return RunGradleInGetOutput('./gradlew', args, cwd, env=env)
-def RunGradleGetOutput(args, env=None):
- return RunGradleInGetOutput(GRADLE, args, utils.REPO_ROOT, env=env)
+def RunGradleGetOutput(args, env=None, new_gradle=False):
+ return RunGradleInGetOutput(
+ get_gradle(new_gradle),
+ args,
+ utils.REPO_ROOT,
+ env=env)
def Main():
(options, args) = ParseOptions()
@@ -114,7 +136,7 @@
args.append('-Pexclude_deps')
if options.worktree:
args.append('-g=' + os.path.join(utils.REPO_ROOT, ".gradle_user_home"))
- return RunGradle(args)
+ return RunGradle(args, new_gradle=options.new_gradle)
if __name__ == '__main__':
sys.exit(Main())
diff --git a/tools/linux/README.art-versions b/tools/linux/README.art-versions
index 611c06e..03ddaa3 100644
--- a/tools/linux/README.art-versions
+++ b/tools/linux/README.art-versions
@@ -65,6 +65,37 @@
(cd tools/linux/host; upload_to_google_storage.py -a --bucket r8-deps art-master)
+repo init -b udc-preview1-release
+
+art-14 (Android U)
+------------------
+Build branch udc-preview1-release.
+
+export BRANCH=udc-preview1-release
+mkdir ${BRANCH}
+cd ${BRANCH}
+export ANDROID_CHECKOUT=$(pwd)
+repo init -u https://android.googlesource.com/platform/manifest -b ${BRANCH}
+repo sync -cq -j48
+source build/envsetup.sh
+lunch aosp_redfin-userdebug
+m -j48
+m -j48 build-art
+m -j48 test-art-host
+repo manifest -r -o build_spec.xml
+
+Collected into tools/linux/host/art-14.0.0-dp1. The "host" path element is checked
+by the script for running Art.
+
+ cd <r8 checkout>
+ scripts/update-host-art.sh \
+ --android-checkout $ANDROID_CHECKOUT \
+ --art-dir host/art-14.0.0-dp1 \
+ --android-product redfin
+
+ (cd tools/linux/host; upload_to_google_storage.py -a --bucket r8-deps art-14.0.0-dp1)
+
+
art-13 (Android T)
------------------
Build branch android-13.0.0_r3.
@@ -86,10 +117,10 @@
cd <r8 checkout>
scripts/update-host-art.sh \
--android-checkout <...>/android-13.0.0_r3 \
- --art-dir host/art-13 \
+ --art-dir host/art-13.0.0 \
--android-product redfin
- (cd tools/linux/host; upload_to_google_storage.py -a --bucket r8-deps art-13)
+ (cd tools/linux/host; upload_to_google_storage.py -a --bucket r8-deps art-13.0.0)
art-12.0.0 (Android S)
---------------------
diff --git a/tools/linux/host/art-14.0.0-dp1.tar.gz.sha1 b/tools/linux/host/art-14.0.0-dp1.tar.gz.sha1
new file mode 100644
index 0000000..c88b923
--- /dev/null
+++ b/tools/linux/host/art-14.0.0-dp1.tar.gz.sha1
@@ -0,0 +1 @@
+1c41f5d79e335ff132b7a95d995b65581c250df8
\ No newline at end of file
diff --git a/tools/test.py b/tools/test.py
index 72b2962..2f0254c 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -28,6 +28,7 @@
ALL_ART_VMS = [
"default",
+ "14.0.0",
"13.0.0",
"12.0.0",
"10.0.0",