Merge commit '4cfe51ef79f7be4b8095d70294410ab25095c1e6' into dev-release
Change-Id: Ib34bee76fd2af418056373e6c0354160cb1db00f
diff --git a/doc/compilerdump.md b/doc/compilerdump.md
index c85a9ff..87976be 100644
--- a/doc/compilerdump.md
+++ b/doc/compilerdump.md
@@ -63,6 +63,17 @@
./gradlew assembleDebug -Dorg.gradle.caching=false -Dcom.android.tools.r8.dumpinputtodirectory=mydumps/ --no-daemon
```
+### Generating a dump in AOSP
+For R8 compilations you can generate dumps with the R8_DUMP_DIRECTORY environment variable.
+This will put dumps for all R8 compilations leading up to the target that you are building.
+For a specific target you can do:
+
+```
+mkdir /tmp/dumps
+R8_DUMP_DIRECTORY=/tmp/dumps m -j77 SystemUI
+```
+The actual dump file for SystemUI will be the last dump in /tmp/dumps.
+
## Reproducing using a dump
@@ -81,3 +92,4 @@
The flags can also be used to override the setting specified in the dump.
Doing so allows compiling with other compiler versions, or other settings.
+
diff --git a/infra/config/global/generated/cr-buildbucket.cfg b/infra/config/global/generated/cr-buildbucket.cfg
index 11b270c..ded5fe1 100644
--- a/infra/config/global/generated/cr-buildbucket.cfg
+++ b/infra/config/global/generated/cr-buildbucket.cfg
@@ -27,8 +27,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -56,8 +56,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -85,8 +85,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -114,8 +114,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -152,8 +152,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -186,8 +186,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -218,8 +218,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -250,8 +250,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -288,8 +288,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -326,8 +326,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -364,8 +364,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -402,8 +402,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -440,8 +440,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -478,8 +478,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -516,8 +516,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -554,8 +554,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -592,8 +592,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -630,8 +630,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -668,8 +668,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -706,8 +706,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -744,8 +744,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -782,8 +782,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -820,8 +820,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -858,8 +858,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -896,8 +896,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -934,8 +934,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -972,8 +972,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1010,8 +1010,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1048,8 +1048,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1086,8 +1086,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1124,8 +1124,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1162,8 +1162,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1199,8 +1199,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1236,8 +1236,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1273,8 +1273,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1305,8 +1305,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1337,8 +1337,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1374,8 +1374,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1411,8 +1411,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1448,8 +1448,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1485,8 +1485,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1522,8 +1522,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1559,8 +1559,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1596,8 +1596,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1633,8 +1633,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1670,8 +1670,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1707,8 +1707,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1744,8 +1744,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1781,8 +1781,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1818,8 +1818,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1852,8 +1852,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1886,8 +1886,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1915,8 +1915,8 @@
dimensions: "os:Ubuntu-20.04"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1944,8 +1944,8 @@
dimensions: "os:Windows-10"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
@@ -1980,8 +1980,8 @@
dimensions: "os:Windows-10"
dimensions: "pool:luci.r8.ci"
exe {
- cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
- cipd_version: "refs/heads/master"
+ cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build"
+ cipd_version: "refs/heads/main"
cmd: "luciexe"
}
properties:
diff --git a/infra/config/global/main.star b/infra/config/global/main.star
index f223381..3e642c0 100755
--- a/infra/config/global/main.star
+++ b/infra/config/global/main.star
@@ -155,9 +155,8 @@
luci.recipe(
name="rex",
cipd_package = "infra_internal/recipe_bundles/" +
- "chrome-internal.googlesource.com/chrome/" +
- "tools/build_limited/scripts/slave",
- cipd_version = "refs/heads/master",
+ "chrome-internal.googlesource.com/chrome/tools/build",
+ cipd_version = "refs/heads/main",
use_bbagent = True
)
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 24d8545..93926dd 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -247,7 +247,7 @@
static void runInternal(AndroidApp app, InternalOptions options, ExecutorService executor)
throws IOException {
- if (options.r8PartialCompilationOptions.enabled) {
+ if (options.partialCompilationConfiguration.isEnabled()) {
try {
new R8Partial(options).runInternal(app, executor);
} catch (ResourceException e) {
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 1077122..6a7475f 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -51,6 +51,7 @@
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.android.tools.r8.utils.InternalOptions.MappingComposeOptions;
import com.android.tools.r8.utils.ProgramClassCollection;
+import com.android.tools.r8.utils.R8PartialCompilationConfiguration;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.SemanticVersion;
import com.android.tools.r8.utils.SetUtils;
@@ -149,6 +150,7 @@
private AndroidResourceConsumer androidResourceConsumer = null;
private ResourceShrinkerConfiguration resourceShrinkerConfiguration =
ResourceShrinkerConfiguration.DEFAULT_CONFIGURATION;
+ private R8PartialCompilationConfiguration partialCompilationConfiguration = null;
private final ProguardConfigurationParserOptions.Builder parserOptionsBuilder =
ProguardConfigurationParserOptions.builder().readEnvironment();
@@ -554,6 +556,43 @@
this.readEmbeddedRulesFromClasspathAndLibrary = enable;
}
+ /**
+ * Configure partial shrinking in R8, where R8 is only applied to a part of the input.
+ *
+ * <p>The patterns in {@code includePatterns} and {@code excludePatterns} are comma separated
+ * lists of string patterns of fully qualified names of packages/classes. The patterns support
+ * the wildcards {@code *} and {@code **}. The wildcards are only supported at the end of the
+ * pattern, so only prefix matching. If the character just before the wildcard is a {@code .}
+ * (package separator) then the difference between {@code *} and {@code **} is that {@code *}
+ * only includes classes in the same package, whereas {@code **} includes classes in subpackages
+ * as well. If the character before the wildcard is not a {@code .} (package separator) then
+ * {@code *} and {@code **} will both match all classes with that prefix.
+ *
+ * <p>If {@code includePatterns} is not specified ({@code null} or an empty string), the default
+ * is {@code "androidx.**,kotlin.**,kotlinx.**"}.
+ *
+ * <p>The include patterns are processed first collecting all possible include classes. Then the
+ * exclude patterns are applied removing all matching classes from the collected include
+ * classes.
+ *
+ * @param includePatterns patterns for classes to include in R8 shrinking (see above for
+ * semantics)
+ * @param excludePatterns patterns for classes to exclude from R8 shrinking (see above for
+ * semantics)
+ * @return
+ */
+ @Deprecated
+ public Builder enableExperimentalPartialShrinking(
+ String includePatterns, String excludePatterns) {
+ if (includePatterns == null || includePatterns.isEmpty()) {
+ includePatterns = "androidx.**,kotlin.**,kotlinx.**";
+ }
+ partialCompilationConfiguration =
+ R8PartialCompilationConfiguration.fromIncludeExcludePatterns(
+ includePatterns, excludePatterns);
+ return self();
+ }
+
@Override
protected InternalProgramOutputPathConsumer createProgramOutputConsumer(
Path path,
@@ -799,7 +838,8 @@
androidResourceConsumer,
resourceShrinkerConfiguration,
keepSpecifications,
- buildMetadataConsumer);
+ buildMetadataConsumer,
+ partialCompilationConfiguration);
if (inputDependencyGraphConsumer != null) {
inputDependencyGraphConsumer.finished();
@@ -1016,6 +1056,7 @@
private final AndroidResourceConsumer androidResourceConsumer;
private final ResourceShrinkerConfiguration resourceShrinkerConfiguration;
private final Consumer<? super R8BuildMetadata> buildMetadataConsumer;
+ private final R8PartialCompilationConfiguration partialCompilationConfiguration;
/** Get a new {@link R8Command.Builder}. */
public static Builder builder() {
@@ -1115,7 +1156,8 @@
AndroidResourceConsumer androidResourceConsumer,
ResourceShrinkerConfiguration resourceShrinkerConfiguration,
List<KeepSpecificationSource> keepSpecifications,
- Consumer<? super R8BuildMetadata> buildMetadataConsumer) {
+ Consumer<? super R8BuildMetadata> buildMetadataConsumer,
+ R8PartialCompilationConfiguration partialCompilationConfiguration) {
super(
inputApp,
mode,
@@ -1165,6 +1207,7 @@
this.androidResourceConsumer = androidResourceConsumer;
this.resourceShrinkerConfiguration = resourceShrinkerConfiguration;
this.buildMetadataConsumer = buildMetadataConsumer;
+ this.partialCompilationConfiguration = partialCompilationConfiguration;
}
private R8Command(boolean printHelp, boolean printVersion) {
@@ -1194,6 +1237,7 @@
androidResourceConsumer = null;
resourceShrinkerConfiguration = null;
buildMetadataConsumer = null;
+ partialCompilationConfiguration = null;
}
public DexItemFactory getDexItemFactory() {
@@ -1343,6 +1387,10 @@
}
// EXPERIMENTAL flags.
+ if (partialCompilationConfiguration != null) {
+ internal.partialCompilationConfiguration = partialCompilationConfiguration;
+ }
+
assert !internal.forceProguardCompatibility;
internal.forceProguardCompatibility = forceProguardCompatibility;
diff --git a/src/main/java/com/android/tools/r8/R8Partial.java b/src/main/java/com/android/tools/r8/R8Partial.java
index e9cb9b8..42b5b5b 100644
--- a/src/main/java/com/android/tools/r8/R8Partial.java
+++ b/src/main/java/com/android/tools/r8/R8Partial.java
@@ -21,9 +21,12 @@
import com.android.tools.r8.tracereferences.TraceReferencesKeepRules;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
import com.android.tools.r8.utils.DumpInputFlags;
+import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
@@ -34,15 +37,37 @@
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
-import java.util.function.Predicate;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
class R8Partial {
private final InternalOptions options;
+ private final Consumer<AndroidApp> r8InputAppConsumer;
+ private final Consumer<AndroidApp> d8InputAppConsumer;
+ private final Consumer<AndroidApp> r8OutputAppConsumer;
+ private final Consumer<AndroidApp> d8OutputAppConsumer;
R8Partial(InternalOptions options) {
this.options = options;
+ this.r8InputAppConsumer = options.partialCompilationConfiguration.r8InputAppConsumer;
+ this.d8InputAppConsumer = options.partialCompilationConfiguration.d8InputAppConsumer;
+ this.r8OutputAppConsumer = options.partialCompilationConfiguration.r8OutputAppConsumer;
+ this.d8OutputAppConsumer = options.partialCompilationConfiguration.d8OutputAppConsumer;
+ }
+
+ static void runForTesting(AndroidApp app, InternalOptions options)
+ throws CompilationFailedException {
+ ExecutorService executor = ThreadUtils.getExecutorService(options);
+ ExceptionUtils.withR8CompilationHandler(
+ options.reporter,
+ () -> {
+ try {
+ new R8Partial(options).runInternal(app, executor);
+ } finally {
+ executor.shutdown();
+ }
+ });
}
void runInternal(AndroidApp app, ExecutorService executor) throws IOException, ResourceException {
@@ -51,8 +76,8 @@
ProgramConsumer originalProgramConsumer = options.programConsumer;
MapConsumer originalMapConsumer = options.mapConsumer;
- Path tmp = options.r8PartialCompilationOptions.getTemp();
- Path dumpFile = options.r8PartialCompilationOptions.getDumpFile();
+ Path tmp = options.partialCompilationConfiguration.getTempDir();
+ Path dumpFile = options.partialCompilationConfiguration.getDumpFile();
// Create a dump of the compiler input.
// TODO(b/309743298): Do not use compiler dump to handle splitting the compilation. This should
@@ -94,15 +119,15 @@
AppInfoWithClassHierarchy.createForDesugaring(
AppInfo.createInitialAppInfo(dapp, GlobalSyntheticsStrategy.forNonSynthesizing()));
- Predicate<String> isR8 = options.r8PartialCompilationOptions.isR8;
- Set<String> d8classes = new HashSet<>();
+ Set<DexProgramClass> d8classes = new HashSet<>();
appInfo
.classes()
.forEach(
clazz -> {
- String key = clazz.toSourceString();
- if (!d8classes.contains(key) && !isR8.test(key)) {
- d8classes.add(key);
+ if (!d8classes.contains(clazz)
+ && !options.partialCompilationConfiguration.test(
+ clazz.getType().getDescriptor())) {
+ d8classes.add(clazz);
// TODO(b/309743298): Improve this to only visit each class once and stop at
// library boundary.
appInfo.forEachSuperType(
@@ -111,7 +136,7 @@
DexProgramClass superClass =
asProgramClassOrNull(appInfo.definitionFor(superType));
if (superClass != null) {
- d8classes.add(superClass.toSourceString());
+ d8classes.add(superClass);
}
});
}
@@ -120,7 +145,7 @@
// Filter the program input into the D8 and R8 parts.
Set<String> d8ZipEntries =
d8classes.stream()
- .map(name -> name.replace('.', '/') + ".class")
+ .map(clazz -> ZipUtils.zipEntryNameForClass(clazz.getClassReference()))
.collect(Collectors.toSet());
ZipBuilder d8ProgramBuilder = ZipBuilder.builder(tmp.resolve("d8-program.jar"));
ZipBuilder r8ProgramBuilder = ZipBuilder.builder(tmp.resolve("r8-program.jar"));
@@ -151,13 +176,23 @@
d8Builder.addDesugaredLibraryConfiguration(
Files.readString(dump.getDesugaredLibraryFile(), UTF_8));
}
+ AndroidAppConsumers d8OutputAppSink = null;
+ if (d8OutputAppConsumer != null) {
+ d8OutputAppSink = new AndroidAppConsumers(d8Builder);
+ }
d8Builder.validate();
D8Command d8command = d8Builder.makeCommand();
AndroidApp d8App = d8command.getInputApp();
+ if (d8InputAppConsumer != null) {
+ d8InputAppConsumer.accept(d8App);
+ }
InternalOptions d8Options = d8command.getInternalOptions();
assert d8Options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
: "Default interface methods not yet supported";
D8.runInternal(d8App, d8Options, executor);
+ if (d8OutputAppConsumer != null) {
+ d8OutputAppConsumer.accept(d8OutputAppSink.build());
+ }
// Run trace references to produce keep rules for the D8 compiled part.
// TODO(b/309743298): Do not emit keep rules into a file.
@@ -192,12 +227,23 @@
r8Builder.addDesugaredLibraryConfiguration(
Files.readString(dump.getDesugaredLibraryFile(), UTF_8));
}
+ AndroidAppConsumers r8OutputAppSink = null;
+ if (r8Builder != null) {
+ r8OutputAppSink = new AndroidAppConsumers(r8Builder);
+ }
+ r8Builder.validate();
R8Command r8Command = r8Builder.makeCommand();
AndroidApp r8App = r8Command.getInputApp();
+ if (r8InputAppConsumer != null) {
+ r8InputAppConsumer.accept(r8App);
+ }
InternalOptions r8Options = r8Command.getInternalOptions();
r8Options.mapConsumer = originalMapConsumer;
r8Options.quiet = true; // Don't write the R8 version.
R8.runInternal(r8App, r8Options, executor);
+ if (r8OutputAppConsumer != null) {
+ r8OutputAppConsumer.accept(r8OutputAppSink.build());
+ }
// Emit resources and merged DEX to the output consumer.
// TODO(b/309743298): Consider passing the DataResourceConsumer to the R8 invocation above.
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 7d9439b..763198e 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -114,14 +114,11 @@
import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicates;
-import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
@@ -1022,9 +1019,10 @@
private final ArtProfileOptions artProfileOptions = new ArtProfileOptions(this);
private final StartupOptions startupOptions = new StartupOptions();
private final InstrumentationOptions instrumentationOptions;
- public final R8PartialCompilationOptions r8PartialCompilationOptions =
- new R8PartialCompilationOptions(
- System.getProperty("com.android.tools.r8.r8PartialCompilation"));
+ public R8PartialCompilationConfiguration partialCompilationConfiguration =
+ R8PartialCompilationConfiguration.fromIncludeExcludePatterns(
+ System.getProperty("com.android.tools.r8.experimentalPartialShrinkingIncludePatterns"),
+ System.getProperty("com.android.tools.r8.experimentalPartialShrinkingExcludePatterns"));
public final TestingOptions testing = new TestingOptions();
public List<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
@@ -2282,39 +2280,6 @@
}
}
- public static class R8PartialCompilationOptions {
- public boolean enabled;
- public Path tempDir = null;
- public Predicate<String> isR8 = null;
-
- R8PartialCompilationOptions(String partialR8) {
- this.enabled = partialR8 != null;
- if (this.enabled) {
- final List<String> prefixes = Splitter.on(",").splitToList(partialR8);
- this.isR8 =
- name -> {
- for (int i = 0; i < prefixes.size(); i++) {
- if (name.startsWith(prefixes.get(i))) {
- return true;
- }
- }
- return false;
- };
- }
- }
-
- public synchronized Path getTemp() throws IOException {
- if (tempDir == null) {
- tempDir = Files.createTempDirectory("r8PartialCompilation");
- }
- return tempDir;
- }
-
- public Path getDumpFile() throws IOException {
- return getTemp().resolve("dump.zip");
- }
- }
-
public static class TestingOptions {
public boolean enableEmbeddedKeepAnnotations =
diff --git a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
new file mode 100644
index 0000000..a1c3b2d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
@@ -0,0 +1,283 @@
+// 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;
+
+import com.android.tools.r8.graph.DexString;
+import com.google.common.base.Predicates;
+import com.google.common.base.Splitter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public class R8PartialCompilationConfiguration implements Predicate<DexString> {
+
+ private final boolean enabled;
+ private Path tempDir = null;
+ private final List<Predicate<DexString>> includePredicates;
+ private final List<Predicate<DexString>> excludePredicates;
+
+ public Consumer<AndroidApp> r8InputAppConsumer;
+ public Consumer<AndroidApp> d8InputAppConsumer;
+ public Consumer<AndroidApp> r8OutputAppConsumer;
+ public Consumer<AndroidApp> d8OutputAppConsumer;
+
+ private static final R8PartialCompilationConfiguration disabledConfiguration =
+ new R8PartialCompilationConfiguration(false, null, null);
+
+ private R8PartialCompilationConfiguration(
+ boolean enabled,
+ List<Predicate<DexString>> includePredicates,
+ List<Predicate<DexString>> excludePredicates) {
+ assert !enabled || !includePredicates.isEmpty();
+ assert !enabled || excludePredicates != null;
+ this.enabled = enabled;
+ this.includePredicates = includePredicates;
+ this.excludePredicates = excludePredicates;
+ }
+
+ @Override
+ public boolean test(DexString name) {
+ for (Predicate<DexString> isR8ClassPredicate : includePredicates) {
+ if (isR8ClassPredicate.test(name)) {
+ for (Predicate<DexString> isD8ClassPredicate : excludePredicates) {
+ if (isD8ClassPredicate.test(name)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static R8PartialCompilationConfiguration disabledConfiguration() {
+ return disabledConfiguration;
+ }
+
+ public static R8PartialCompilationConfiguration fromIncludeExcludePatterns(
+ String includePatterns, String excludePatterns) {
+ boolean enabled = includePatterns != null || excludePatterns != null;
+ if (!enabled) {
+ return disabledConfiguration();
+ }
+ Builder builder = builder();
+ if (includePatterns != null) {
+ Splitter.on(",").splitToList(includePatterns).forEach(builder::addJavaTypeIncludePattern);
+ }
+ if (excludePatterns != null) {
+ Splitter.on(",").splitToList(excludePatterns).forEach(builder::addJavaTypeExcludePattern);
+ }
+ return builder.build();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public synchronized Path getTempDir() throws IOException {
+ if (tempDir == null) {
+ setTempDir(Files.createTempDirectory("r8PartialCompilation"));
+ }
+ return tempDir;
+ }
+
+ public void setTempDir(Path tempDir) {
+ this.tempDir = tempDir;
+ }
+
+ public Path getDumpFile() throws IOException {
+ return getTempDir().resolve("dump.zip");
+ }
+
+ public static class Builder {
+ private final List<Predicate<DexString>> includePredicates = new ArrayList<>();
+ private final List<Predicate<DexString>> excludePredicates = new ArrayList<>();
+
+ private Builder() {}
+
+ public R8PartialCompilationConfiguration build() {
+ return new R8PartialCompilationConfiguration(
+ !includePredicates.isEmpty(), includePredicates, excludePredicates);
+ }
+
+ public Builder includeAll() {
+ includePredicates.add(Predicates.alwaysTrue());
+ return this;
+ }
+
+ public Builder addJavaTypeIncludePattern(String pattern) {
+ includePredicates.add(
+ createMatcher("L" + DescriptorUtils.getBinaryNameFromJavaType(pattern)));
+ return this;
+ }
+
+ public Builder addJavaTypeExcludePattern(String pattern) {
+ excludePredicates.add(
+ createMatcher("L" + DescriptorUtils.getBinaryNameFromJavaType(pattern)));
+ return this;
+ }
+
+ public Builder addDescriptorIncludePattern(String pattern) {
+ includePredicates.add(createMatcher(pattern));
+ return this;
+ }
+
+ public Builder addDescriptorExcludePattern(String pattern) {
+ excludePredicates.add(createMatcher(pattern));
+ return this;
+ }
+
+ private Predicate<DexString> createMatcher(String descriptorPrefix) {
+ assert descriptorPrefix.startsWith("L");
+ assert descriptorPrefix.indexOf('.') == -1;
+
+ if (descriptorPrefix.equals("L**")) {
+ return new AllClassesMatcher();
+ } else if (descriptorPrefix.equals("L*")) {
+ return new UnnamedPackageMatcher();
+ } else if (descriptorPrefix.endsWith("/**")) {
+ return new PackageAndSubpackagePrefixMatcher(
+ descriptorPrefix.substring(0, descriptorPrefix.length() - 2));
+ } else if (descriptorPrefix.endsWith("/*")) {
+ return new PackagePrefixMatcher(
+ descriptorPrefix.substring(0, descriptorPrefix.length() - 1));
+ }
+ if (descriptorPrefix.endsWith("*")) {
+ return new ClassPrefixMatcher(descriptorPrefix.substring(0, descriptorPrefix.length() - 1));
+ } else {
+ return new ClassNameMatcher(descriptorPrefix + ';');
+ }
+ }
+
+ public Builder includeClasses(Class<?>... classes) {
+ return includeClasses(Arrays.asList(classes));
+ }
+
+ public Builder includeClasses(Collection<Class<?>> classes) {
+ classes.forEach(
+ clazz ->
+ includePredicates.add(
+ descriptor ->
+ descriptor.toString().equals(DescriptorUtils.javaClassToDescriptor(clazz))));
+ return this;
+ }
+
+ public Builder includeJavaType(Predicate<String> include) {
+ includePredicates.add(
+ descriptor -> include.test(DescriptorUtils.descriptorToJavaType(descriptor.toString())));
+ return this;
+ }
+
+ public Builder excludeClasses(Class<?>... classes) {
+ return excludeClasses(Arrays.asList(classes));
+ }
+
+ public Builder excludeClasses(Collection<Class<?>> classes) {
+ classes.forEach(
+ clazz ->
+ excludePredicates.add(
+ descriptor ->
+ descriptor.toString().equals(DescriptorUtils.javaClassToDescriptor(clazz))));
+ return this;
+ }
+
+ public Builder excludeJavaType(Predicate<String> exclude) {
+ excludePredicates.add(
+ descriptor -> exclude.test(DescriptorUtils.descriptorToJavaType(descriptor.toString())));
+ return this;
+ }
+ }
+
+ private static class AllClassesMatcher implements Predicate<DexString> {
+
+ AllClassesMatcher() {}
+
+ @Override
+ public boolean test(DexString descriptor) {
+ return true;
+ }
+ }
+
+ private static class UnnamedPackageMatcher implements Predicate<DexString> {
+
+ UnnamedPackageMatcher() {}
+
+ @Override
+ public boolean test(DexString descriptor) {
+ return descriptor.indexOf('/') == -1;
+ }
+ }
+
+ private static class PackageAndSubpackagePrefixMatcher implements Predicate<DexString> {
+
+ private final byte[] descriptorPrefix;
+
+ PackageAndSubpackagePrefixMatcher(String descriptorPrefix) {
+ this.descriptorPrefix = DexString.encodeToMutf8(descriptorPrefix);
+ }
+
+ @Override
+ public boolean test(DexString descriptor) {
+ return descriptor.startsWith(descriptorPrefix);
+ }
+ }
+
+ private static class PackagePrefixMatcher implements Predicate<DexString> {
+
+ private final byte[] descriptorPrefix;
+ private final int descriptorPrefixLength;
+
+ PackagePrefixMatcher(String descriptorPrefix) {
+ this.descriptorPrefix = DexString.encodeToMutf8(descriptorPrefix);
+ this.descriptorPrefixLength = descriptorPrefix.length();
+ }
+
+ @Override
+ public boolean test(DexString descriptor) {
+ return descriptor.startsWith(descriptorPrefix)
+ && descriptor.lastIndexOf('/') == descriptorPrefixLength - 1;
+ }
+ }
+
+ private static class ClassPrefixMatcher implements Predicate<DexString> {
+
+ private final byte[] descriptorPrefix;
+ private final int descriptorPrefixLength;
+
+ ClassPrefixMatcher(String descriptorPrefix) {
+ this.descriptorPrefix = DexString.encodeToMutf8(descriptorPrefix);
+ this.descriptorPrefixLength = descriptorPrefix.length();
+ }
+
+ @Override
+ public boolean test(DexString descriptor) {
+ return descriptor.startsWith(descriptorPrefix)
+ && descriptor.lastIndexOf('/') < descriptorPrefixLength - 1;
+ }
+ }
+
+ private static class ClassNameMatcher implements Predicate<DexString> {
+
+ private final String descriptor;
+
+ ClassNameMatcher(String descriptor) {
+ this.descriptor = descriptor;
+ }
+
+ @Override
+ public boolean test(DexString descriptor) {
+ return descriptor.toString().equals(this.descriptor);
+ }
+ }
+}
diff --git a/src/test/examplesJava9/twraddsuppressed/TestClass.java b/src/test/examplesJava9/twraddsuppressed/TestClass.java
index 61285ce..fcf0d6f 100644
--- a/src/test/examplesJava9/twraddsuppressed/TestClass.java
+++ b/src/test/examplesJava9/twraddsuppressed/TestClass.java
@@ -20,6 +20,8 @@
}
public static void bar() {
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
+ //
// Use twr twice to have javac generate a shared $closeResource helper.
try (MyClosable closable = new MyClosable()) {
foo();
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 5d349fc..bd1aace 100644
--- a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
+++ b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
@@ -36,6 +36,7 @@
import com.android.tools.r8.compilerapi.testsetup.ApiTestingSetUpTest;
import com.android.tools.r8.compilerapi.wrappers.CommandLineParserTest;
import com.android.tools.r8.compilerapi.wrappers.EnableMissingLibraryApiModelingTest;
+import com.android.tools.r8.partial.PartialShrinkingPreviewApiTest;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -79,7 +80,7 @@
MainDexRulesTest.ApiTest.class);
private static final List<Class<? extends CompilerApiTest>> CLASSES_PENDING_BINARY_COMPATIBILITY =
- ImmutableList.of();
+ ImmutableList.of(PartialShrinkingPreviewApiTest.ApiTest.class);
private final TemporaryFolder temp;
diff --git a/src/test/java/com/android/tools/r8/desugar/suppressedexceptions/TwrSuppressedExceptionsTest.java b/src/test/java/com/android/tools/r8/desugar/suppressedexceptions/TwrSuppressedExceptionsTest.java
index ce7e1a7..6c03e85 100644
--- a/src/test/java/com/android/tools/r8/desugar/suppressedexceptions/TwrSuppressedExceptionsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/suppressedexceptions/TwrSuppressedExceptionsTest.java
@@ -84,6 +84,7 @@
ClassSubject clazz = inspector.clazz(MAIN.typeName());
hasInvokesTo(
clazz.uniqueMethodWithOriginalName("bar"),
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
"$closeResource",
apiLevelHasTwrCloseResourceSupport(true) ? 4 : 0);
if (apiLevelHasSuppressedExceptionsSupport(true)) {
@@ -102,6 +103,7 @@
DesugarTestConfiguration::isNotDesugared,
inspector -> {
ClassSubject clazz = inspector.clazz(MAIN.typeName());
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
hasInvokesTo(clazz.uniqueMethodWithOriginalName("bar"), "$closeResource", 4);
hasInvokesTo(clazz.mainMethod(), "getSuppressed", 1);
});
diff --git a/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java b/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java
index b5b8444..dbea1507 100644
--- a/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java
@@ -110,6 +110,8 @@
.assertSuccessWithOutput(EXPECTED)
.inspect(
inspector -> {
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
+ //
// There should be two synthetic classes besides the three program classes.
// One for the desugar version of TWR $closeResource and one for the
// Throwable.addSuppressed that is still present in the original $closeResource.
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/CloseResourceMethod.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/CloseResourceMethod.java
index 2059e86..7e18bdb 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/CloseResourceMethod.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/CloseResourceMethod.java
@@ -8,6 +8,9 @@
public class CloseResourceMethod {
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler. The test
+ // CheckTwrOutputForJavaCompilersTest will fail if it is generated by other compilers.
+ //
// The following method defines the code of
//
// public static void $closeResource(Throwable throwable, Object resource)
diff --git a/src/test/java/com/android/tools/r8/partial/ClassHierarchyInterleavedD8AndR8Test.java b/src/test/java/com/android/tools/r8/partial/ClassHierarchyInterleavedD8AndR8Test.java
index db45859..32bfa65 100644
--- a/src/test/java/com/android/tools/r8/partial/ClassHierarchyInterleavedD8AndR8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/ClassHierarchyInterleavedD8AndR8Test.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.partial;
import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -13,9 +14,10 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.R8PartialCompilationConfiguration;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.function.Predicate;
+import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -40,15 +42,18 @@
}
private void runTest(
- Predicate<String> isR8, ThrowingConsumer<CodeInspector, RuntimeException> inspector)
+ Consumer<R8PartialCompilationConfiguration.Builder> partialConfigurationBuilderConsumer,
+ ThrowingConsumer<CodeInspector, RuntimeException> d8Inspector,
+ ThrowingConsumer<CodeInspector, RuntimeException> inspector)
throws Exception {
// Path tempDir = temp.newFolder().toPath();
testForR8Partial(parameters.getBackend())
.setMinApi(parameters)
.addProgramClasses(A.class, B.class, C.class, Main.class)
.addKeepMainRule(Main.class)
- .setR8PartialConfigurationPredicate(isR8)
+ .setR8PartialConfiguration(partialConfigurationBuilderConsumer)
.compile()
+ .inspectD8Input(d8Inspector)
.inspect(inspector)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithEmptyOutput();
@@ -57,7 +62,13 @@
@Test
public void testD8Top() throws Exception {
runTest(
- name -> !name.equals(A.class.getTypeName()),
+ partialConfigurationBuilder ->
+ partialConfigurationBuilder.includeAll().excludeClasses(A.class),
+ inspector -> {
+ assertThat(inspector.programClass(A.class), isPresent());
+ assertThat(inspector.programClass(B.class), isAbsent());
+ assertThat(inspector.programClass(C.class), isAbsent());
+ },
inspector -> {
assertThat(inspector.clazz(A.class), isPresentAndNotRenamed());
assertThat(inspector.clazz(B.class), isAbsent()); // Merged into C.
@@ -68,7 +79,13 @@
@Test
public void testD8Middle() throws Exception {
runTest(
- name -> !name.equals(B.class.getTypeName()),
+ partialConfigurationBuilder ->
+ partialConfigurationBuilder.includeAll().excludeClasses(B.class),
+ inspector -> {
+ assertThat(inspector.programClass(A.class), isPresent());
+ assertThat(inspector.programClass(B.class), isPresent());
+ assertThat(inspector.programClass(C.class), isAbsent());
+ },
inspector -> {
assertThat(inspector.clazz(A.class), isPresentAndNotRenamed());
assertThat(inspector.clazz(B.class), isPresentAndNotRenamed());
@@ -79,7 +96,13 @@
@Test
public void testD8Bottom() throws Exception {
runTest(
- name -> !name.equals(C.class.getTypeName()),
+ partialConfigurationBuilder ->
+ partialConfigurationBuilder.includeAll().excludeClasses(C.class),
+ inspector -> {
+ assertThat(inspector.programClass(A.class), isPresent());
+ assertThat(inspector.programClass(B.class), isPresent());
+ assertThat(inspector.programClass(C.class), isPresent());
+ },
inspector -> {
assertThat(inspector.clazz(A.class), isPresentAndNotRenamed());
assertThat(inspector.clazz(B.class), isPresentAndNotRenamed());
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
new file mode 100644
index 0000000..b6c55e9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
@@ -0,0 +1,286 @@
+// 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.partial;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.partial.pkg1.A1;
+import com.android.tools.r8.partial.pkg1.A2;
+import com.android.tools.r8.partial.pkg1.subpkg.B;
+import com.android.tools.r8.partial.pkg2.C1;
+import com.android.tools.r8.partial.pkg2.C2;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+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 PartialCompilationBasicPreviewPatternsTest extends TestBase {
+
+ private static String PKG1 = getPackageName(A1.class);
+ private static String SUBPKG = getPackageName(B.class);
+ private static String PKG2 = getPackageName(C2.class);
+
+ private static String getPackageName(Class<?> clazz) {
+ return clazz.getTypeName().substring(0, clazz.getTypeName().lastIndexOf('.'));
+ }
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ // Test with min API level 24.
+ public static TestParametersCollection data() {
+ return getTestParameters()
+ .withDexRuntime(DexVm.Version.V7_0_0)
+ .withApiLevel(AndroidApiLevel.N)
+ .build();
+ }
+
+ private static final List<Class<?>> ALL_CLASSES =
+ ImmutableList.of(A1.class, A2.class, B.class, C1.class, C2.class, Main.class);
+ private static final String[] ALL_TYPE_NAMES =
+ new String[] {
+ A1.class.getTypeName(),
+ A2.class.getTypeName(),
+ B.class.getTypeName(),
+ C1.class.getTypeName(),
+ C2.class.getTypeName()
+ };
+
+ @Test
+ public void pkg1AndSubpackagesCompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(builder -> builder.addJavaTypeIncludePattern(PKG1 + ".**"))
+ .compile()
+ .inspectD8Input(
+ inspector ->
+ assertTrue(inspector.hasExactlyProgramClasses(C1.class, C2.class, Main.class)))
+ .inspectR8Input(
+ inspector ->
+ assertTrue(inspector.hasExactlyProgramClasses(A1.class, A2.class, B.class)))
+ .inspect(
+ inspector ->
+ assertTrue(inspector.hasExactlyProgramClasses(C1.class, C2.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Not instantiated",
+ "Not instantiated",
+ "Not instantiated",
+ "Instantiated",
+ "Instantiated");
+ }
+
+ @Test
+ public void pkg1CompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(builder -> builder.addJavaTypeIncludePattern(PKG1 + ".*"))
+ .compile()
+ .inspectD8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(B.class, C1.class, C2.class, Main.class)))
+ .inspectR8Input(
+ inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, A2.class)))
+ .inspect(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(B.class, C1.class, C2.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Not instantiated", "Not instantiated", "Instantiated", "Instantiated", "Instantiated");
+ }
+
+ @Test
+ public void pkg1AndSubpackagesExcludeSubPkgCompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(
+ builder ->
+ builder
+ .addJavaTypeIncludePattern(PKG1 + ".**")
+ .addJavaTypeExcludePattern(SUBPKG + ".*"))
+ .compile()
+ .inspectD8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(C1.class, C2.class, B.class, Main.class)))
+ .inspectR8Input(
+ inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, A2.class)))
+ .inspect(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(B.class, C1.class, C2.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Not instantiated", "Not instantiated", "Instantiated", "Instantiated", "Instantiated");
+ }
+
+ @Test
+ public void pkg1AndSubpackagesExcludeAPrefixCompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(
+ builder ->
+ builder
+ .addJavaTypeIncludePattern(PKG1 + ".**")
+ .addJavaTypeExcludePattern(PKG1 + ".A*"))
+ .compile()
+ .inspectD8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(
+ A1.class, A2.class, C1.class, C2.class, Main.class)))
+ .inspectR8Input(inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class)))
+ .inspect(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(
+ A1.class, A2.class, C1.class, C2.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Instantiated", "Instantiated", "Not instantiated", "Instantiated", "Instantiated");
+ }
+
+ @Test
+ public void pkg1AndSubpackagesExcludeA1AndA2CompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(
+ builder ->
+ builder
+ .addJavaTypeIncludePattern(PKG1 + ".**")
+ .addJavaTypeExcludePattern(PKG1 + ".A1")
+ .addJavaTypeExcludePattern(PKG1 + ".A2"))
+ .compile()
+ .inspectD8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(
+ A1.class, A2.class, C1.class, C2.class, Main.class)))
+ .inspectR8Input(inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class)))
+ .inspect(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(
+ A1.class, A2.class, C1.class, C2.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Instantiated", "Instantiated", "Not instantiated", "Instantiated", "Instantiated");
+ }
+
+ @Test
+ public void allExeptC1CompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(
+ builder ->
+ builder
+ .addJavaTypeIncludePattern(PKG1 + ".**")
+ .addJavaTypeIncludePattern(PKG2 + ".**")
+ .addJavaTypeExcludePattern(PKG2 + ".C1"))
+ .compile()
+ .inspectD8Input(
+ inspector -> assertTrue(inspector.hasExactlyProgramClasses(C1.class, Main.class)))
+ .inspectR8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(A1.class, A2.class, B.class, C2.class)))
+ .inspect(inspector -> assertTrue(inspector.hasExactlyProgramClasses(C1.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Not instantiated",
+ "Not instantiated",
+ "Not instantiated",
+ "Instantiated",
+ "Not instantiated");
+ }
+
+ @Test
+ public void allExeptA1CompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(
+ builder ->
+ builder
+ .addJavaTypeIncludePattern(PKG1 + ".*")
+ .addJavaTypeIncludePattern(SUBPKG + ".*")
+ .addJavaTypeIncludePattern(PKG2 + ".*")
+ .addJavaTypeExcludePattern(PKG1 + ".A1"))
+ .compile()
+ .inspectD8Input(
+ inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, Main.class)))
+ .inspectR8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(A2.class, B.class, C1.class, C2.class)))
+ .inspect(inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Instantiated",
+ "Not instantiated",
+ "Not instantiated",
+ "Not instantiated",
+ "Not instantiated");
+ }
+
+ @Test
+ public void allExeptBCompiledWithR8() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(ALL_CLASSES)
+ .setR8PartialConfiguration(
+ builder ->
+ builder
+ .addJavaTypeIncludePattern(PKG1 + ".**")
+ .addJavaTypeIncludePattern(PKG2 + ".**")
+ .addJavaTypeExcludePattern(SUBPKG + ".*"))
+ .compile()
+ .inspectD8Input(
+ inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class, Main.class)))
+ .inspectR8Input(
+ inspector ->
+ assertTrue(
+ inspector.hasExactlyProgramClasses(A1.class, A2.class, C1.class, C2.class)))
+ .inspect(inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class, Main.class)))
+ .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
+ .assertSuccessWithOutputLines(
+ "Not instantiated",
+ "Not instantiated",
+ "Instantiated",
+ "Not instantiated",
+ "Not instantiated");
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) throws Exception {
+ for (String arg : args) {
+ try {
+ Class.forName(arg);
+ System.out.println("Instantiated");
+ } catch (ClassNotFoundException e) {
+ System.out.println("Not instantiated");
+ }
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
index 662aa21..e55a8d5 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
@@ -39,12 +39,37 @@
.setMinApi(parameters)
.addProgramClasses(A.class, B.class, Main.class)
.addKeepMainRule(Main.class)
- .setR8PartialConfiguration(builder -> builder.includeAll().excludeClasses(A.class).build())
+ .setR8PartialConfiguration(builder -> builder.includeAll().excludeClasses(A.class))
.compile()
+ .inspectR8Input(
+ inspector -> {
+ assertThat(inspector.programClass(A.class), isAbsent());
+ assertThat(inspector.programClass(B.class), isPresent());
+ assertThat(inspector.programClass(Main.class), isPresent());
+ })
+ .inspectD8Input(
+ inspector -> {
+ assertThat(inspector.programClass(A.class), isPresent());
+ assertThat(inspector.programClass(B.class), isAbsent());
+ assertThat(inspector.programClass(Main.class), isAbsent());
+ })
+ .inspectR8Output(
+ inspector -> {
+ assertThat(inspector.clazz(A.class), isAbsent());
+ assertThat(inspector.clazz(B.class), isAbsent());
+ assertThat(inspector.clazz(Main.class), isPresent());
+ })
+ .inspectD8Output(
+ inspector -> {
+ assertThat(inspector.clazz(A.class), isPresent());
+ assertThat(inspector.clazz(B.class), isAbsent());
+ assertThat(inspector.clazz(Main.class), isAbsent());
+ })
.inspect(
inspector -> {
assertThat(inspector.clazz(A.class), isPresent());
assertThat(inspector.clazz(B.class), isAbsent());
+ assertThat(inspector.clazz(Main.class), isPresent());
})
.run(parameters.getRuntime(), Main.class, getClass().getTypeName())
.assertSuccessWithOutputLines("Instantiated", "Not instantiated");
@@ -56,12 +81,41 @@
.setMinApi(parameters)
.addProgramClasses(A.class, B.class, Main.class)
.addKeepMainRule(Main.class)
- .setR8PartialConfiguration(builder -> builder.includeAll().excludeClasses(B.class).build())
+ .setR8PartialConfiguration(builder -> builder.includeAll().excludeClasses(B.class))
.compile()
+ .inspectR8Input(
+ inspector -> {
+ // TODO(b/309743298): These are all present as inspection currently also look at
+ // classpath.
+ assertThat(inspector.programClass(A.class), isPresent());
+ assertThat(inspector.programClass(B.class), isAbsent());
+ assertThat(inspector.programClass(Main.class), isPresent());
+ })
+ .inspectD8Input(
+ inspector -> {
+ // TODO(b/309743298): These are all present as inspection currently also look at
+ // classpath.
+ assertThat(inspector.programClass(A.class), isAbsent());
+ assertThat(inspector.programClass(B.class), isPresent());
+ assertThat(inspector.programClass(Main.class), isAbsent());
+ })
+ .inspectR8Output(
+ inspector -> {
+ assertThat(inspector.clazz(A.class), isAbsent());
+ assertThat(inspector.clazz(B.class), isAbsent());
+ assertThat(inspector.clazz(Main.class), isPresent());
+ })
+ .inspectD8Output(
+ inspector -> {
+ assertThat(inspector.clazz(A.class), isAbsent());
+ assertThat(inspector.clazz(B.class), isPresent());
+ assertThat(inspector.clazz(Main.class), isAbsent());
+ })
.inspect(
inspector -> {
assertThat(inspector.clazz(A.class), isAbsent());
assertThat(inspector.clazz(B.class), isPresent());
+ assertThat(inspector.clazz(Main.class), isPresent());
})
.run(parameters.getRuntime(), Main.class, getClass().getTypeName())
.assertSuccessWithOutputLines("Not instantiated", "Instantiated");
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
index 0ccd8ce..43ad334 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
@@ -236,10 +236,10 @@
private void runR8Partial(Path tempDir, CompilerDump dump, Path output, Predicate<String> isR8)
throws IOException, CompilationFailedException {
testForR8Partial(parameters.getBackend())
- .setR8PartialConfigurationPredicate(isR8)
+ .setR8PartialConfigurationJavaTypePredicate(isR8)
.addOptionsModification(
options -> {
- options.r8PartialCompilationOptions.tempDir = tempDir;
+ options.partialCompilationConfiguration.setTempDir(tempDir);
// For compiling nowonandroid.
options.testing.allowUnnecessaryDontWarnWildcards = true;
diff --git a/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java b/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
new file mode 100644
index 0000000..f5784c5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
@@ -0,0 +1,78 @@
+// 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.partial;
+
+import static com.android.tools.r8.MarkerMatcher.markerMinApi;
+import static com.android.tools.r8.MarkerMatcher.markerR8Mode;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.ProgramConsumer;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+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.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.ThrowingConsumer;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.file.Path;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+
+public class PartialShrinkingPreviewApiTest extends CompilerApiTestRunner {
+
+ public static final int MIN_API_LEVEL = 31;
+
+ public PartialShrinkingPreviewApiTest(TestParameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public Class<? extends CompilerApiTest> binaryTestClass() {
+ return ApiTest.class;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+ runTest(test::runR8);
+ }
+
+ private void runTest(ThrowingConsumer<ProgramConsumer, Exception> test) throws Exception {
+ Path output = temp.newFolder().toPath().resolve("out.jar");
+ test.accept(new DexIndexedConsumer.ArchiveConsumer(output));
+ assertThat(
+ new CodeInspector(output).getMarkers(),
+ CoreMatchers.everyItem(
+ CoreMatchers.allOf(
+ markerMinApi(AndroidApiLevel.getAndroidApiLevel(MIN_API_LEVEL)),
+ markerR8Mode("full"))));
+ }
+
+ public static class ApiTest extends CompilerApiTest {
+
+ public ApiTest(Object parameters) {
+ super(parameters);
+ }
+
+ public void runR8(ProgramConsumer programConsumer) throws Exception {
+ R8.run(
+ R8Command.builder()
+ .addClassProgramData(getBytesForClass(getMockClass()), Origin.unknown())
+ .addProguardConfiguration(getKeepMainRules(getMockClass()), Origin.unknown())
+ .addLibraryFiles(getJava8RuntimeJar())
+ .setProgramConsumer(programConsumer)
+ .enableExperimentalPartialShrinking("**", null)
+ .setMinApiLevel(MIN_API_LEVEL)
+ .build());
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ runR8(DexIndexedConsumer.emptyConsumer());
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/partial/pkg1/A1.java b/src/test/java/com/android/tools/r8/partial/pkg1/A1.java
new file mode 100644
index 0000000..e435721
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/pkg1/A1.java
@@ -0,0 +1,6 @@
+// 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.partial.pkg1;
+
+public class A1 {}
diff --git a/src/test/java/com/android/tools/r8/partial/pkg1/A2.java b/src/test/java/com/android/tools/r8/partial/pkg1/A2.java
new file mode 100644
index 0000000..7cac5c2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/pkg1/A2.java
@@ -0,0 +1,6 @@
+// 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.partial.pkg1;
+
+public class A2 {}
diff --git a/src/test/java/com/android/tools/r8/partial/pkg1/subpkg/B.java b/src/test/java/com/android/tools/r8/partial/pkg1/subpkg/B.java
new file mode 100644
index 0000000..ee4cb46
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/pkg1/subpkg/B.java
@@ -0,0 +1,6 @@
+// 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.partial.pkg1.subpkg;
+
+public class B {}
diff --git a/src/test/java/com/android/tools/r8/partial/pkg2/C1.java b/src/test/java/com/android/tools/r8/partial/pkg2/C1.java
new file mode 100644
index 0000000..a6225c1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/pkg2/C1.java
@@ -0,0 +1,6 @@
+// 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.partial.pkg2;
+
+public class C1 {}
diff --git a/src/test/java/com/android/tools/r8/partial/pkg2/C2.java b/src/test/java/com/android/tools/r8/partial/pkg2/C2.java
new file mode 100644
index 0000000..139666a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/pkg2/C2.java
@@ -0,0 +1,6 @@
+// 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.partial.pkg2;
+
+public class C2 {}
diff --git a/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java b/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java
index f840c33f..3bb5e4c 100644
--- a/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java
@@ -98,6 +98,7 @@
ImmutableList.of(Reference.classFromClass(String.class)),
null))
.addMethodRule(
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
Reference.method(
FOO.getClassReference(), "$closeResource", closeResourceFormalParameters, null))
.addMethodRule(
@@ -107,6 +108,7 @@
ImmutableList.of(Reference.classFromClass(String.class)),
null))
.addMethodRule(
+ // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
Reference.method(
BAR.getClassReference(), "$closeResource", closeResourceFormalParameters, null))
.build();
diff --git a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
index 319b633..3dacb92 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
@@ -10,23 +10,17 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.InternalOptions;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
+import com.android.tools.r8.utils.R8PartialCompilationConfiguration;
import java.util.List;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
public class R8PartialTestBuilder
extends R8TestBuilder<R8PartialTestCompileResult, R8TestRunResult, R8PartialTestBuilder> {
- private R8PartialConfiguration r8PartialConfiguration =
- R8PartialConfiguration.defaultConfiguration();
+ private R8PartialCompilationConfiguration r8PartialConfiguration =
+ R8PartialCompilationConfiguration.disabledConfiguration();
private R8PartialTestBuilder(TestState state, Builder builder, Backend backend) {
super(state, builder, backend);
@@ -52,106 +46,30 @@
return this;
}
- public static class R8PartialConfiguration implements Predicate<String> {
- private static final R8PartialConfiguration defaultConfiguration =
- new R8PartialConfiguration(ImmutableList.of(), ImmutableList.of());
- private final List<Predicate<String>> includePredicates;
- private final List<Predicate<String>> excludePredicates;
-
- public R8PartialConfiguration(
- List<Predicate<String>> includePredicates, List<Predicate<String>> excludePredicates) {
- this.includePredicates = includePredicates;
- this.excludePredicates = excludePredicates;
- }
-
- private static R8PartialConfiguration defaultConfiguration() {
- return defaultConfiguration;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public boolean test(String name) {
- for (Predicate<String> isR8ClassPredicate : includePredicates) {
- if (isR8ClassPredicate.test(name)) {
- for (Predicate<String> isD8ClassPredicate : excludePredicates) {
- if (isD8ClassPredicate.test(name)) {
- return false;
- }
- }
- return true;
- }
- }
- return false;
- }
-
- public static class Builder {
- private final List<Predicate<String>> includePredicates = new ArrayList<>();
- private final List<Predicate<String>> excludePredicates = new ArrayList<>();
-
- public R8PartialConfiguration build() {
- return new R8PartialConfiguration(includePredicates, excludePredicates);
- }
-
- public Builder includeAll() {
- includePredicates.add(Predicates.alwaysTrue());
- return this;
- }
-
- public Builder includeClasses(Class<?>... classes) {
- return includeClasses(Arrays.asList(classes));
- }
-
- public Builder includeClasses(Collection<Class<?>> classes) {
- Collection<String> typeNames =
- classes.stream().map(Class::getTypeName).collect(Collectors.toList());
- includePredicates.add(typeNames::contains);
- return this;
- }
-
- public Builder include(Predicate<String> include) {
- includePredicates.add(include);
- return this;
- }
-
- public Builder excludeClasses(Class<?>... classes) {
- return excludeClasses(Arrays.asList(classes));
- }
-
- public Builder excludeClasses(Collection<Class<?>> classes) {
- Collection<String> typeNames =
- classes.stream().map(Class::getTypeName).collect(Collectors.toList());
- excludePredicates.add(typeNames::contains);
- return this;
- }
-
- public Builder exclude(Predicate<String> exclude) {
- excludePredicates.add(exclude);
- return this;
- }
- }
- }
-
- public R8PartialTestBuilder setR8PartialConfigurationPredicate(Predicate<String> include) {
- assert r8PartialConfiguration == R8PartialConfiguration.defaultConfiguration()
+ public R8PartialTestBuilder setR8PartialConfigurationJavaTypePredicate(
+ Predicate<String> include) {
+ assert r8PartialConfiguration.equals(R8PartialCompilationConfiguration.disabledConfiguration())
: "Overwriting configuration...?";
- r8PartialConfiguration = R8PartialConfiguration.builder().include(include).build();
+ r8PartialConfiguration =
+ R8PartialCompilationConfiguration.builder().includeJavaType(include).build();
return self();
}
- public R8PartialTestBuilder setR8PartialConfiguration(R8PartialConfiguration configuration) {
- assert r8PartialConfiguration == R8PartialConfiguration.defaultConfiguration()
+ public R8PartialTestBuilder setR8PartialConfiguration(
+ R8PartialCompilationConfiguration configuration) {
+ assert r8PartialConfiguration.equals(R8PartialCompilationConfiguration.disabledConfiguration())
: "Overwriting configuration...?";
r8PartialConfiguration = configuration;
return self();
}
public R8PartialTestBuilder setR8PartialConfiguration(
- Function<R8PartialConfiguration.Builder, R8PartialConfiguration> fn) {
- assert r8PartialConfiguration == R8PartialConfiguration.defaultConfiguration()
+ Consumer<R8PartialCompilationConfiguration.Builder> consumer) {
+ assert r8PartialConfiguration.equals(R8PartialCompilationConfiguration.disabledConfiguration())
: "Overwriting configuration...?";
- r8PartialConfiguration = fn.apply(R8PartialConfiguration.builder());
+ R8PartialCompilationConfiguration.Builder builder = R8PartialCompilationConfiguration.builder();
+ consumer.accept(builder);
+ r8PartialConfiguration = builder.build();
return self();
}
@@ -165,12 +83,19 @@
Box<List<ProguardConfigurationRule>> syntheticProguardRulesConsumer,
StringBuilder proguardMapBuilder)
throws CompilationFailedException {
+ Box<AndroidApp> r8InputAppBox = new Box<>();
+ Box<AndroidApp> d8InputAppBox = new Box<>();
+ Box<AndroidApp> r8OutputAppBox = new Box<>();
+ Box<AndroidApp> d8OutputAppBox = new Box<>();
Consumer<InternalOptions> configureR8PartialCompilation =
options -> {
- options.r8PartialCompilationOptions.enabled = true;
- options.r8PartialCompilationOptions.isR8 = r8PartialConfiguration;
+ options.partialCompilationConfiguration = r8PartialConfiguration;
+ options.partialCompilationConfiguration.r8InputAppConsumer = r8InputAppBox::set;
+ options.partialCompilationConfiguration.d8InputAppConsumer = d8InputAppBox::set;
+ options.partialCompilationConfiguration.r8OutputAppConsumer = r8OutputAppBox::set;
+ options.partialCompilationConfiguration.d8OutputAppConsumer = d8OutputAppBox::set;
};
- ToolHelper.runAndBenchmarkR8WithoutResult(
+ ToolHelper.runAndBenchmarkR8PartialWithoutResult(
builder, configureR8PartialCompilation.andThen(optionsConsumer), benchmarkResults);
return new R8PartialTestCompileResult(
getState(),
@@ -186,6 +111,10 @@
residualArtProfiles,
resourceShrinkerOutput,
resourceShrinkerOutputForFeatures,
- buildMetadata != null ? buildMetadata.get() : null);
+ buildMetadata != null ? buildMetadata.get() : null,
+ r8InputAppBox.get(),
+ d8InputAppBox.get(),
+ r8OutputAppBox.get(),
+ d8OutputAppBox.get());
}
}
diff --git a/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java b/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java
index 18f75fb..2ff5569 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java
@@ -8,13 +8,23 @@
import com.android.tools.r8.shaking.CollectingGraphConsumer;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ThrowingConsumer;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
+import java.util.function.Consumer;
public class R8PartialTestCompileResult
extends R8TestCompileResultBase<R8PartialTestCompileResult> {
+ private final AndroidApp r8InputApp;
+ private final AndroidApp d8InputApp;
+ private final AndroidApp r8OutputApp;
+ private final AndroidApp d8OutputApp;
+
R8PartialTestCompileResult(
TestState state,
OutputMode outputMode,
@@ -29,7 +39,11 @@
List<ExternalArtProfile> residualArtProfiles,
Path resourceShrinkerOutput,
HashMap<String, Path> resourceShrinkerOutputForFeatures,
- R8BuildMetadata buildMetadata) {
+ R8BuildMetadata buildMetadata,
+ AndroidApp r8InputApp,
+ AndroidApp d8InputApp,
+ AndroidApp r8OutputApp,
+ AndroidApp d8OutputApp) {
super(
state,
outputMode,
@@ -45,10 +59,74 @@
resourceShrinkerOutput,
resourceShrinkerOutputForFeatures,
buildMetadata);
+ this.r8InputApp = r8InputApp;
+ this.d8InputApp = d8InputApp;
+ this.r8OutputApp = r8OutputApp;
+ this.d8OutputApp = d8OutputApp;
}
@Override
public R8PartialTestCompileResult self() {
return this;
}
+
+ public CodeInspector inspectorR8Input() throws IOException {
+ return new CodeInspector(r8InputApp);
+ }
+
+ public CodeInspector inspectorR8Input(Consumer<InternalOptions> debugOptionsConsumer)
+ throws IOException {
+ return new CodeInspector(r8InputApp, debugOptionsConsumer);
+ }
+
+ public <E extends Throwable> R8PartialTestCompileResult inspectR8Input(
+ ThrowingConsumer<CodeInspector, E> consumer) throws IOException, E {
+ consumer.accept(inspectorR8Input());
+ return self();
+ }
+
+ public CodeInspector inspectorD8Input() throws IOException {
+ return new CodeInspector(d8InputApp);
+ }
+
+ public CodeInspector inspectorD8Input(Consumer<InternalOptions> debugOptionsConsumer)
+ throws IOException {
+ return new CodeInspector(d8InputApp, debugOptionsConsumer);
+ }
+
+ public <E extends Throwable> R8PartialTestCompileResult inspectD8Input(
+ ThrowingConsumer<CodeInspector, E> consumer) throws IOException, E {
+ consumer.accept(inspectorD8Input());
+ return self();
+ }
+
+ public CodeInspector inspectorR8Output() throws IOException {
+ return new CodeInspector(r8OutputApp);
+ }
+
+ public CodeInspector inspectorR8Output(Consumer<InternalOptions> debugOptionsConsumer)
+ throws IOException {
+ return new CodeInspector(r8OutputApp, debugOptionsConsumer);
+ }
+
+ public <E extends Throwable> R8PartialTestCompileResult inspectR8Output(
+ ThrowingConsumer<CodeInspector, E> consumer) throws IOException, E {
+ consumer.accept(inspectorR8Output());
+ return self();
+ }
+
+ public CodeInspector inspectorD8Output() throws IOException {
+ return new CodeInspector(d8OutputApp);
+ }
+
+ public CodeInspector inspectorD8Output(Consumer<InternalOptions> debugOptionsConsumer)
+ throws IOException {
+ return new CodeInspector(d8OutputApp, debugOptionsConsumer);
+ }
+
+ public <E extends Throwable> R8PartialTestCompileResult inspectD8Output(
+ ThrowingConsumer<CodeInspector, E> consumer) throws IOException, E {
+ consumer.accept(inspectorD8Output());
+ return self();
+ }
}
diff --git a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
index 1a8a049..0608acb 100644
--- a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
@@ -1807,6 +1807,28 @@
}
}
+ public static void runAndBenchmarkR8PartialWithoutResult(
+ R8Command.Builder commandBuilder,
+ Consumer<InternalOptions> optionsConsumer,
+ BenchmarkResults benchmarkResults)
+ throws CompilationFailedException {
+ long start = 0;
+ if (benchmarkResults != null) {
+ start = System.nanoTime();
+ }
+ R8Command command = commandBuilder.build();
+ InternalOptions internalOptions = command.getInternalOptions();
+ optionsConsumer.accept(internalOptions);
+ try {
+ R8Partial.runForTesting(command.getInputApp(), internalOptions);
+ } finally {
+ if (benchmarkResults != null) {
+ long end = System.nanoTime();
+ benchmarkResults.addRuntimeResult(end - start);
+ }
+ }
+ }
+
public static AndroidApp runR8WithFullResult(
R8Command command, Consumer<InternalOptions> optionsConsumer)
throws CompilationFailedException {
diff --git a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 7c06d42..d9af1e0 100644
--- a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.utils.codeinspector;
import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
+import static com.android.tools.r8.utils.codeinspector.CodeInspector.ClassType.ANY;
+import static com.android.tools.r8.utils.codeinspector.CodeInspector.ClassType.PROGRAM;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.StringResource;
@@ -45,6 +47,7 @@
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BiMapContainer;
+import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
@@ -61,6 +64,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -78,6 +82,11 @@
final Map<String, String> obfuscatedToOriginalMapping;
private Retracer lazyRetracer = null;
+ public enum ClassType {
+ PROGRAM,
+ ANY
+ }
+
public static MethodSignature MAIN =
new MethodSignature("main", "void", new String[] {"java.lang.String[]"});
@@ -293,6 +302,10 @@
return rewriter.getSignature();
}
+ public ClassSubject clazz(Class<?> clazz, ClassType classType) {
+ return clazz(Reference.classFromClass(clazz), classType);
+ }
+
public ClassSubject clazz(Class<?> clazz) {
return clazz(Reference.classFromClass(clazz));
}
@@ -302,6 +315,10 @@
return clazz(Reference.classFromTypeName(name));
}
+ public ClassSubject programClass(Class<?> clazz) {
+ return clazz(Reference.classFromClass(clazz), PROGRAM);
+ }
+
public ClassNameMapper getMapping() {
return mapping;
}
@@ -355,7 +372,7 @@
}
}
- public ClassSubject clazz(ClassReference reference) {
+ public ClassSubject clazz(ClassReference reference, ClassType classType) {
String descriptor = reference.getDescriptor();
String name = DescriptorUtils.descriptorToJavaType(descriptor);
ClassNamingForNameMapper naming = null;
@@ -374,13 +391,20 @@
}
}
}
- DexClass clazz = application.definitionFor(toDexTypeIgnorePrimitives(name));
+ DexClass clazz =
+ classType == ANY
+ ? application.definitionFor(toDexTypeIgnorePrimitives(name))
+ : application.programDefinitionFor(toDexTypeIgnorePrimitives(name));
if (clazz == null) {
return new AbsentClassSubject(this, reference);
}
return new FoundClassSubject(this, clazz, MappingWrapper.create(mapping, naming), reference);
}
+ public ClassSubject clazz(ClassReference reference) {
+ return clazz(reference, ANY);
+ }
+
public ClassSubject companionClassFor(Class<?> clazz) {
return clazz(SyntheticItemsTestUtils.syntheticCompanionClass(clazz));
}
@@ -402,6 +426,18 @@
return builder.build();
}
+ public boolean hasExactlyProgramClasses(Class<?>... classes) {
+ return hasExactlyProgramClasses(Arrays.asList(classes));
+ }
+
+ public boolean hasExactlyProgramClasses(Collection<Class<?>> classes) {
+ Set<ClassReference> descriptors =
+ classes.stream().map(Reference::classFromClass).collect(Collectors.toSet());
+ BooleanBox allFound = new BooleanBox(true);
+ forAllClasses(clazz -> allFound.and(descriptors.remove(clazz.reference)));
+ return descriptors.isEmpty() && allFound.get();
+ }
+
public Stream<InstructionSubject> streamInstructions() {
return allClasses().stream()
.flatMap(cls -> cls.allMethods(MethodSubject::hasCode).stream())