Reland "Account for art profiles in compiledump.py"
This reverts commit f065e0c1c145fb76ff94198eb719d73e90821436.
Change-Id: If8cd6a56ceff69524df8b216d0341cb55d5649e1
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/tools/compiledump.py b/tools/compiledump.py
index 843c0b1..9c495a1 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:
@@ -316,6 +326,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')
@@ -412,7 +425,7 @@
return False
def prepare_r8_wrapper(dist, temp, jdkhome):
- compile_with_javac(
+ compile_wrapper_with_javac(
dist,
temp,
jdkhome,
@@ -421,7 +434,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,
@@ -429,10 +442,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,
]
@@ -545,6 +562,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: