Extend compile dump utils to startup profiles
Change-Id: I609c75a7445e674cc76737768cefbcd1fc0cbd15
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java
index ae95407..3aea957 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java
@@ -9,18 +9,68 @@
import com.android.tools.r8.experimental.startup.profile.art.ARTProfileBuilderUtils.SyntheticToSyntheticContextGeneralization;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.startup.StartupProfileBuilder;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.startup.diagnostic.MissingStartupProfileItemsDiagnostic;
import com.android.tools.r8.utils.ConsumerUtils;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.MethodReferenceUtils;
import com.android.tools.r8.utils.UTF8TextInputStream;
+import java.io.BufferedReader;
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.nio.file.Files;
import java.nio.file.Path;
public class StartupProfileProviderUtils {
+ public static StartupProfileProvider createFromDumpFile(Path path) {
+ return new StartupProfileProvider() {
+
+ @Override
+ public void getStartupProfile(StartupProfileBuilder startupProfileBuilder) {
+ try {
+ try (BufferedReader bufferedReader = Files.newBufferedReader(path)) {
+ while (bufferedReader.ready()) {
+ String rule = bufferedReader.readLine();
+ if (rule.charAt(0) == 'S') {
+ String classDescriptor = rule.substring(1);
+ assert DescriptorUtils.isClassDescriptor(classDescriptor);
+ startupProfileBuilder.addSyntheticStartupMethod(
+ syntheticStartupMethodBuilder ->
+ syntheticStartupMethodBuilder.setSyntheticContextReference(
+ Reference.classFromDescriptor(classDescriptor)));
+ } else {
+ MethodReference methodReference = MethodReferenceUtils.parseSmaliString(rule);
+ if (methodReference != null) {
+ startupProfileBuilder.addStartupMethod(
+ startupMethodBuilder ->
+ startupMethodBuilder.setMethodReference(methodReference));
+ } else {
+ assert DescriptorUtils.isClassDescriptor(rule);
+ startupProfileBuilder.addStartupClass(
+ startupClassBuilder ->
+ startupClassBuilder.setClassReference(
+ Reference.classFromDescriptor(rule)));
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ @Override
+ public Origin getOrigin() {
+ return new PathOrigin(path);
+ }
+ };
+ }
+
public static StartupProfileProvider createFromHumanReadableARTProfile(Path path) {
return new StartupProfileProvider() {
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/art/HumanReadableARTProfileParser.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/art/HumanReadableARTProfileParser.java
index 29ffaa6..e86501f 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/profile/art/HumanReadableARTProfileParser.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/profile/art/HumanReadableARTProfileParser.java
@@ -8,18 +8,15 @@
import com.android.tools.r8.origin.Origin;
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.references.TypeReference;
import com.android.tools.r8.startup.diagnostic.HumanReadableARTProfileParserErrorDiagnostic;
import com.android.tools.r8.utils.Action;
-import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.ClassReferenceUtils;
+import com.android.tools.r8.utils.MethodReferenceUtils;
import com.android.tools.r8.utils.Reporter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
-import java.util.ArrayList;
-import java.util.List;
public class HumanReadableARTProfileParser {
@@ -94,7 +91,7 @@
}
private boolean parseClassRule(String descriptor) {
- ClassReference classReference = parseClassDescriptor(descriptor);
+ ClassReference classReference = ClassReferenceUtils.parseClassDescriptor(descriptor);
if (classReference == null) {
return false;
}
@@ -104,7 +101,8 @@
private boolean parseMethodRule(
String descriptor, ARTProfileMethodRuleInfoImpl methodRuleInfo, int arrowStartIndex) {
- MethodReference methodReference = parseMethodDescriptor(descriptor, arrowStartIndex);
+ MethodReference methodReference =
+ MethodReferenceUtils.parseSmaliString(descriptor, arrowStartIndex);
if (methodReference == null) {
return false;
}
@@ -112,46 +110,6 @@
return true;
}
- private ClassReference parseClassDescriptor(String classDescriptor) {
- if (DescriptorUtils.isClassDescriptor(classDescriptor)) {
- return Reference.classFromDescriptor(classDescriptor);
- } else {
- return null;
- }
- }
-
- private MethodReference parseMethodDescriptor(
- String startupMethodDescriptor, int arrowStartIndex) {
- String classDescriptor = startupMethodDescriptor.substring(0, arrowStartIndex);
- ClassReference methodHolder = parseClassDescriptor(classDescriptor);
- if (methodHolder == null) {
- return null;
- }
-
- int methodNameStartIndex = arrowStartIndex + 2;
- String protoWithNameDescriptor = startupMethodDescriptor.substring(methodNameStartIndex);
- int methodNameEndIndex = protoWithNameDescriptor.indexOf('(');
- if (methodNameEndIndex <= 0) {
- return null;
- }
- String methodName = protoWithNameDescriptor.substring(0, methodNameEndIndex);
-
- String protoDescriptor = protoWithNameDescriptor.substring(methodNameEndIndex);
- return parseMethodProto(methodHolder, methodName, protoDescriptor);
- }
-
- private MethodReference parseMethodProto(
- ClassReference methodHolder, String methodName, String protoDescriptor) {
- List<TypeReference> parameterTypes = new ArrayList<>();
- for (String parameterTypeDescriptor :
- DescriptorUtils.getArgumentTypeDescriptors(protoDescriptor)) {
- parameterTypes.add(Reference.typeFromDescriptor(parameterTypeDescriptor));
- }
- String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(protoDescriptor);
- TypeReference returnType = Reference.returnTypeFromDescriptor(returnTypeDescriptor);
- return Reference.method(methodHolder, methodName, parameterTypes, returnType);
- }
-
public static class Builder {
private ARTProfileBuilder profileBuilder;
diff --git a/src/main/java/com/android/tools/r8/utils/ClassReferenceUtils.java b/src/main/java/com/android/tools/r8/utils/ClassReferenceUtils.java
index 30754f0..072022d 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassReferenceUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassReferenceUtils.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
import java.util.Comparator;
public class ClassReferenceUtils {
@@ -36,6 +37,14 @@
return COMPARATOR;
}
+ public static ClassReference parseClassDescriptor(String classDescriptor) {
+ if (DescriptorUtils.isClassDescriptor(classDescriptor)) {
+ return Reference.classFromDescriptor(classDescriptor);
+ } else {
+ return null;
+ }
+ }
+
public static DexType toDexType(ClassReference classReference, DexItemFactory dexItemFactory) {
return dexItemFactory.createType(classReference.getDescriptor());
}
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 3c2605a..82f1ce4 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
+import com.android.tools.r8.experimental.startup.StartupProfileProviderUtils;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
@@ -24,6 +25,7 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Wrapper to make it easy to call R8 in compat mode when compiling a dump file.
@@ -58,7 +60,8 @@
"--pg-conf",
"--pg-map-output",
"--desugared-lib",
- "--threads");
+ "--threads",
+ "--startup-profile");
private static final List<String> VALID_OPTIONS_WITH_TWO_OPERANDS =
Arrays.asList("--feature-jar");
@@ -84,6 +87,7 @@
List<Path> classpath = new ArrayList<>();
List<Path> config = new ArrayList<>();
List<Path> mainDexRulesFiles = new ArrayList<>();
+ List<Path> startupProfileFiles = new ArrayList<>();
int minApi = 1;
int threads = -1;
boolean enableMissingLibraryApiModeling = false;
@@ -169,6 +173,11 @@
mainDexRulesFiles.add(Paths.get(operand));
break;
}
+ case "--startup-profile":
+ {
+ startupProfileFiles.add(Paths.get(operand));
+ break;
+ }
default:
throw new IllegalArgumentException("Unimplemented option: " + option);
}
@@ -201,6 +210,10 @@
.addClasspathFiles(classpath)
.addProguardConfigurationFiles(config)
.addMainDexRulesFiles(mainDexRulesFiles)
+ .addStartupProfileProviders(
+ startupProfileFiles.stream()
+ .map(StartupProfileProviderUtils::createFromDumpFile)
+ .collect(Collectors.toList()))
.setOutput(outputPath, outputMode)
.setMode(compilationMode);
getReflectiveBuilderMethod(
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 b2c4269..f1007f6 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpD8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpD8.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.experimental.startup.StartupProfileProviderUtils;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
@@ -19,6 +20,7 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Wrapper to make it easy to call D8 mode when compiling a dump file.
@@ -50,7 +52,8 @@
"--main-dex-list",
"--main-dex-list-output",
"--desugared-lib",
- "--threads");
+ "--threads",
+ "--startup-profile");
public static void main(String[] args) throws CompilationFailedException {
OutputMode outputMode = OutputMode.DexIndexed;
@@ -61,6 +64,7 @@
List<Path> library = new ArrayList<>();
List<Path> classpath = new ArrayList<>();
List<Path> mainDexRulesFiles = new ArrayList<>();
+ List<Path> startupProfileFiles = new ArrayList<>();
int minApi = 1;
int threads = -1;
boolean enableMissingLibraryApiModeling = false;
@@ -131,6 +135,11 @@
mainDexRulesFiles.add(Paths.get(operand));
break;
}
+ case "--startup-profile":
+ {
+ startupProfileFiles.add(Paths.get(operand));
+ break;
+ }
default:
throw new IllegalArgumentException("Unimplemented option: " + option);
}
@@ -144,6 +153,10 @@
.addLibraryFiles(library)
.addClasspathFiles(classpath)
.addMainDexRulesFiles(mainDexRulesFiles)
+ .addStartupProfileProviders(
+ startupProfileFiles.stream()
+ .map(StartupProfileProviderUtils::createFromDumpFile)
+ .collect(Collectors.toList()))
.setOutput(outputPath, outputMode)
.setMode(compilationMode);
getReflectiveBuilderMethod(
diff --git a/src/main/java/com/android/tools/r8/utils/MethodReferenceUtils.java b/src/main/java/com/android/tools/r8/utils/MethodReferenceUtils.java
index 4e1a4bc..251edcc 100644
--- a/src/main/java/com/android/tools/r8/utils/MethodReferenceUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/MethodReferenceUtils.java
@@ -16,9 +16,11 @@
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
+import java.util.List;
public class MethodReferenceUtils {
@@ -106,6 +108,46 @@
}
}
+ public static MethodReference parseSmaliString(String classAndMethodDescriptor) {
+ int arrowStartIndex = classAndMethodDescriptor.indexOf("->");
+ if (arrowStartIndex >= 0) {
+ return parseSmaliString(classAndMethodDescriptor, arrowStartIndex);
+ }
+ return null;
+ }
+
+ public static MethodReference parseSmaliString(
+ String classAndMethodDescriptor, int arrowStartIndex) {
+ String classDescriptor = classAndMethodDescriptor.substring(0, arrowStartIndex);
+ ClassReference methodHolder = ClassReferenceUtils.parseClassDescriptor(classDescriptor);
+ if (methodHolder == null) {
+ return null;
+ }
+
+ int methodNameStartIndex = arrowStartIndex + 2;
+ String protoWithNameDescriptor = classAndMethodDescriptor.substring(methodNameStartIndex);
+ int methodNameEndIndex = protoWithNameDescriptor.indexOf('(');
+ if (methodNameEndIndex <= 0) {
+ return null;
+ }
+ String methodName = protoWithNameDescriptor.substring(0, methodNameEndIndex);
+
+ String protoDescriptor = protoWithNameDescriptor.substring(methodNameEndIndex);
+ return parseMethodProto(methodHolder, methodName, protoDescriptor);
+ }
+
+ private static MethodReference parseMethodProto(
+ ClassReference methodHolder, String methodName, String protoDescriptor) {
+ List<TypeReference> parameterTypes = new ArrayList<>();
+ for (String parameterTypeDescriptor :
+ DescriptorUtils.getArgumentTypeDescriptors(protoDescriptor)) {
+ parameterTypes.add(Reference.typeFromDescriptor(parameterTypeDescriptor));
+ }
+ String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(protoDescriptor);
+ TypeReference returnType = Reference.returnTypeFromDescriptor(returnTypeDescriptor);
+ return Reference.method(methodHolder, methodName, parameterTypes, returnType);
+ }
+
public static DexMethod toDexMethod(
MethodReference methodReference, DexItemFactory dexItemFactory) {
return dexItemFactory.createMethod(
diff --git a/tools/compiledump.py b/tools/compiledump.py
index 6baaada..8149313 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -189,12 +189,21 @@
print("Unimplemented: proguard_input configuration.")
def main_dex_list_resource(self):
- if self.if_exists('main-dex-list.txt'):
- print("Unimplemented: main-dex-list.")
+ return self.if_exists('main-dex-list.txt')
def main_dex_rules_resource(self):
return self.if_exists('main-dex-rules.txt')
+ def startup_profile_resources(self):
+ startup_profile_resources = []
+ while True:
+ current_startup_profile_index = len(startup_profile_resources) + 1
+ startup_profile_resource = self.if_exists(
+ 'startup-profile-%s.txt' % current_startup_profile_index)
+ if startup_profile_resource is None:
+ return startup_profile_resources
+ startup_profile_resources.append(startup_profile_resource)
+
def build_properties_file(self):
return self.if_exists('build.properties')
@@ -470,8 +479,12 @@
# -print{mapping,usage}
clean_config(dump.config_file(), args)
cmd.extend(['--pg-conf', dump.config_file()])
+ if dump.main_dex_list_resource():
+ 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 startup_profile_resource in dump.startup_profile_resources():
+ cmd.extend(['--startup-profile', startup_profile_resource])
if compiler == 'l8':
if dump.config_file():
cmd.extend(['--pg-map-output', '%s.map' % out])