Don't use reflective lookup for calling command builder code
This will compile a set of java files against TOT, allowing us to
directly use the api instead of reflective lookup.
We put this on classpath for the compiledump invocation, and catch any
missing class or method errors.
New files in this directory are automatically compiled, but one should
ensure that functionality that are added in different versions of R8
are added to different files (to avoid issues loading the class for
old functionality)
This only enables this for resource shrinker, I will change the rest
if we agree on this approach.
Bug: b/377606434
Change-Id: I6db890440de6c188f5da15c55723fc1579523c17
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java b/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java
index a5aadef..12e971a 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpBase.java
@@ -34,22 +34,6 @@
.accept(new Object[] {isolatedSplits});
}
- static void setupResourceShrinking(
- Path androidResourcesInput, Path androidResourcesOutput, Object builder) {
- try {
- Class<?> androidResourceProvider =
- Class.forName("com.android.tools.r8.AndroidResourceProvider");
- Class<?> androidResourceConsumer =
- Class.forName("com.android.tools.r8.AndroidResourceConsumer");
- getReflectiveBuilderMethod(builder, "setAndroidResourceProvider", androidResourceProvider)
- .accept(new Object[] {createAndroidResourceProvider(androidResourcesInput)});
- getReflectiveBuilderMethod(builder, "setAndroidResourceConsumer", androidResourceConsumer)
- .accept(new Object[] {createAndroidResourceConsumer(androidResourcesOutput)});
- } catch (ClassNotFoundException e) {
- // Ignore
- }
- }
-
static void addArtProfilesForRewriting(Object builder, Map<Path, Path> artProfileFiles) {
try {
Class<?> artProfileProviderClass =
@@ -98,16 +82,6 @@
return returnObject[0];
}
- static Object createAndroidResourceProvider(Path resourceInput) {
- return callReflectiveDumpUtilsMethodWithPath(
- resourceInput, "createAndroidResourceProviderFromDumpFile");
- }
-
- static Object createAndroidResourceConsumer(Path resourceOutput) {
- return callReflectiveDumpUtilsMethodWithPath(
- resourceOutput, "createAndroidResourceConsumerFromDumpFile");
- }
-
static Object createArtProfileProvider(Path artProfile) {
return callReflectiveDumpUtilsMethodWithPath(
artProfile, "createArtProfileProviderFromDumpFile");
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 9112b77..e9e8ae5 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
@@ -10,8 +10,8 @@
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
-import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.StringConsumer;
+import com.android.tools.r8.utils.compiledump.ResourceShrinker;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -228,7 +228,7 @@
program.add(Paths.get(option));
}
}
- Builder commandBuilder =
+ R8Command.Builder commandBuilder =
new CompatProguardCommandBuilder(isCompatMode)
.addProgramFiles(program)
.addLibraryFiles(library)
@@ -246,7 +246,13 @@
commandBuilder.addDesugaredLibraryConfiguration(readAllBytesJava7(desugaredLibJson));
}
if (androidResourcesInput != null) {
- setupResourceShrinking(androidResourcesInput, androidResourcesOutput, commandBuilder);
+ Path finalAndroidResourcesInput = androidResourcesInput;
+ Path finalAndroidResourcesOutput = androidResourcesOutput;
+ runIgnoreMissing(
+ () ->
+ ResourceShrinker.setupBaseResourceShrinking(
+ finalAndroidResourcesInput, finalAndroidResourcesOutput, commandBuilder),
+ "Failed initializing resource shrinker.");
}
if (desugaredLibKeepRuleConsumer != null) {
commandBuilder.setDesugaredLibraryKeepRuleConsumer(desugaredLibKeepRuleConsumer);
@@ -277,4 +283,12 @@
R8.run(command);
}
}
+
+ private static void runIgnoreMissing(Runnable runnable, String onMissing) {
+ try {
+ runnable.run();
+ } catch (NoClassDefFoundError | NoSuchMethodError e) {
+ System.out.println(onMissing);
+ }
+ }
}
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 ef013f6..2f9a820 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpUtils.java
@@ -38,16 +38,6 @@
}
@KeepMethodForCompileDump
- static AndroidResourceProvider createAndroidResourceProviderFromDumpFile(Path resourceInput) {
- return new ArchiveProtoAndroidResourceProvider(resourceInput);
- }
-
- @KeepMethodForCompileDump
- static AndroidResourceConsumer createAndroidResourceConsumerFromDumpFile(Path resourceOutput) {
- return new ArchiveProtoAndroidResourceConsumer(resourceOutput);
- }
-
- @KeepMethodForCompileDump
static StartupProfileProvider createStartupProfileProviderFromDumpFile(Path path) {
return new StartupProfileProvider() {
diff --git a/src/main/java/com/android/tools/r8/utils/compiledump/ResourceShrinker.java b/src/main/java/com/android/tools/r8/utils/compiledump/ResourceShrinker.java
new file mode 100644
index 0000000..67d0322
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/compiledump/ResourceShrinker.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2024, 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.compiledump;
+
+import com.android.tools.r8.ArchiveProtoAndroidResourceConsumer;
+import com.android.tools.r8.ArchiveProtoAndroidResourceProvider;
+import com.android.tools.r8.R8Command;
+import java.nio.file.Path;
+
+public class ResourceShrinker {
+ public static void setupBaseResourceShrinking(
+ Path input, Path output, R8Command.Builder builder) {
+ builder.setAndroidResourceProvider(new ArchiveProtoAndroidResourceProvider(input));
+ builder.setAndroidResourceConsumer(new ArchiveProtoAndroidResourceConsumer(output));
+ }
+}
diff --git a/tools/compiledump.py b/tools/compiledump.py
index c819865..d92bf82 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -502,7 +502,25 @@
return False
+def compile_reflective_helper(temp, jdkhome):
+ gradle.RunGradle([utils.GRADLE_TASK_MAIN_COMPILE])
+ base_path = os.path.join(
+ utils.REPO_ROOT,
+ 'src/main/java/com/android/tools/r8/utils/compiledumputils')
+
+ cmd = [
+ jdk.GetJavacExecutable(jdkhome),
+ '-d',
+ temp,
+ '-cp',
+ utils.BUILD_JAVA_MAIN_DIR,
+ ]
+ cmd.extend(os.path.join(base_path, f) for f in os.listdir(base_path))
+ utils.PrintCmd(cmd)
+ subprocess.check_output(cmd)
+
def prepare_r8_wrapper(dist, temp, jdkhome):
+ compile_reflective_helper(temp, jdkhome)
compile_wrapper_with_javac(
dist, temp, jdkhome,
os.path.join(
@@ -530,7 +548,7 @@
'-d',
temp,
'-cp',
- dist,
+ "%s:%s" % (dist, temp),
]
utils.PrintCmd(cmd)
subprocess.check_output(cmd)
diff --git a/tools/utils.py b/tools/utils.py
index 86d7e8d..66f8e36 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -32,7 +32,8 @@
DEPENDENCIES_DIR = os.path.join(THIRD_PARTY, 'dependencies')
BUILD = os.path.join(REPO_ROOT, 'build')
-BUILD_JAVA_MAIN_DIR = os.path.join(BUILD, 'classes', 'java', 'main')
+BUILD_JAVA_MAIN_DIR = os.path.join(REPO_ROOT, 'd8_r8', 'main', 'build',
+ 'classes', 'java', 'main')
LIBS = os.path.join(BUILD, 'libs')
CUSTOM_CONVERSION_DIR = os.path.join(THIRD_PARTY, 'openjdk',
'custom_conversion')
@@ -44,6 +45,7 @@
GRADLE_TASK_CONSOLIDATED_LICENSE = ':main:consolidatedLicense'
GRADLE_TASK_KEEP_ANNO_JAR = ':keepanno:keepAnnoAnnotationsJar'
GRADLE_TASK_KEEP_ANNO_DOC = ':keepanno:keepAnnoAnnotationsDoc'
+GRADLE_TASK_MAIN_COMPILE = ':main:compileJava'
GRADLE_TASK_R8 = ':main:r8WithRelocatedDeps'
GRADLE_TASK_R8LIB = ':test:assembleR8LibWithRelocatedDeps'
GRADLE_TASK_R8LIB_NO_DEPS = ':test:assembleR8LibNoDeps'