Merge commit '8d24db72a19fc0420001e20db9765ebf277d188d' into dev-release
diff --git a/.gitignore b/.gitignore
index c97f9a0..7ad6f32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -127,6 +127,8 @@
third_party/openjdk/desugar_jdk_libs.tar.gz
third_party/openjdk/desugar_jdk_libs_11
third_party/openjdk/desugar_jdk_libs_11.tar.gz
+third_party/openjdk/desugar_jdk_libs_legacy
+third_party/openjdk/desugar_jdk_libs_legacy.tar.gz
third_party/openjdk/desugar_jdk_libs_releases/1.0.9
third_party/openjdk/desugar_jdk_libs_releases/1.0.9.tar.gz
third_party/openjdk/desugar_jdk_libs_releases/1.0.10
diff --git a/build.gradle b/build.gradle
index bd5538a..8a6e218 100644
--- a/build.gradle
+++ b/build.gradle
@@ -367,6 +367,7 @@
"openjdk/openjdk-rt-1.8",
"openjdk/desugar_jdk_libs",
"openjdk/desugar_jdk_libs_11",
+ "openjdk/desugar_jdk_libs_legacy",
"openjdk/desugar_jdk_libs_releases/1.0.9",
"openjdk/desugar_jdk_libs_releases/1.0.10",
"openjdk/desugar_jdk_libs_releases/1.1.0",
@@ -1019,7 +1020,7 @@
dependsOn r8WithRelocatedDeps
dependsOn r8Task
commandLine ([
- "python", "tools/create_r8lib.py",
+ "python3", "tools/create_r8lib.py",
"--r8jar", r8Task.outputs.files[0],
"--output", output]
+ (pgConfs.collectMany { ["--pg-conf", it] })
@@ -1068,7 +1069,7 @@
inputs.file script
outputs.dir outputDir
dependsOn downloadDeps
- commandLine "python", script
+ commandLine "python3", script
workingDir = projectDir
}
@@ -1186,7 +1187,7 @@
inputs.files files("tests/2017-10-04/art.tar.gz", createArtTestsScript)
outputs.dir outputDir
dependsOn downloadDeps
- commandLine "python", createArtTestsScript
+ commandLine "python3", createArtTestsScript
workingDir = projectDir
}
@@ -1196,7 +1197,7 @@
inputs.file script
outputs.dir outputDir
dependsOn downloadDeps
- commandLine "python", script
+ commandLine "python3", script
workingDir = projectDir
}
@@ -1875,7 +1876,7 @@
def retrace(Throwable exception) {
def out = new StringBuffer()
def err = new StringBuffer()
- def command = "python tools/retrace.py --quiet"
+ def command = "python3 tools/retrace.py --quiet"
def header = "RETRACED STACKTRACE";
out.append("\n--------------------------------------\n")
out.append("${header}\n")
diff --git a/infra/config/global/generated/luci-scheduler.cfg b/infra/config/global/generated/luci-scheduler.cfg
index 629ee37..cb2a721 100644
--- a/infra/config/global/generated/luci-scheduler.cfg
+++ b/infra/config/global/generated/luci-scheduler.cfg
@@ -691,7 +691,7 @@
triggers: "linux-android-12.0.0_release"
gitiles {
repo: "https://r8.googlesource.com/r8"
- refs: "regexp:refs/heads//([3]\\.[2-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"
+ refs: "regexp:refs/heads/([3]\\.[2-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"
path_regexps: "src/main/java/com/android/tools/r8/Version.java"
}
}
@@ -702,7 +702,7 @@
triggers: "linux-android-13.0.0_release"
gitiles {
repo: "https://r8.googlesource.com/r8"
- refs: "regexp:refs/heads//([3]\\.[3-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"
+ refs: "regexp:refs/heads/([3]\\.[3-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"
path_regexps: "src/main/java/com/android/tools/r8/Version.java"
}
}
diff --git a/infra/config/global/main.star b/infra/config/global/main.star
index 6c59f26..d6eb25a 100755
--- a/infra/config/global/main.star
+++ b/infra/config/global/main.star
@@ -112,7 +112,7 @@
name = "branch-gitiles-3.3-forward",
bucket = "ci",
repo = "https://r8.googlesource.com/r8",
- refs = ["refs/heads//([3]\\.[3-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"],
+ refs = ["refs/heads/([3]\\.[3-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"],
path_regexps = ["src/main/java/com/android/tools/r8/Version.java"]
)
@@ -120,7 +120,7 @@
name = "branch-gitiles-3.2-forward",
bucket = "ci",
repo = "https://r8.googlesource.com/r8",
- refs = ["refs/heads//([3]\\.[2-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"],
+ refs = ["refs/heads/([3]\\.[2-9]+(\\.[0-9]+)?|[4-9]\\.[0-9]+(\\.[0-9]+)?)"],
path_regexps = ["src/main/java/com/android/tools/r8/Version.java"]
)
diff --git a/src/library_desugar/desugar_jdk_libs_alternative_3.json b/src/library_desugar/desugar_jdk_libs_alternative_3.json
deleted file mode 100644
index 2b0ffd9..0000000
--- a/src/library_desugar/desugar_jdk_libs_alternative_3.json
+++ /dev/null
@@ -1,254 +0,0 @@
-{
- "configuration_format_version": 3,
- "group_id" : "com.tools.android",
- "artifact_id" : "desugar_jdk_libs_alternative_3",
- "version": "1.2.1",
- "required_compilation_api_level": 26,
- "synthesized_library_classes_package_prefix": "j$.",
- "support_all_callbacks_from_library": false,
- "common_flags": [
- {
- "api_level_below_or_equal": 25,
- "wrapper_conversion": [
- "java.time.Clock"
- ]
- },
- {
- "api_level_below_or_equal": 23,
- "wrapper_conversion": [
- "java.util.PrimitiveIterator$OfDouble",
- "java.util.PrimitiveIterator$OfInt",
- "java.util.PrimitiveIterator$OfLong",
- "java.util.Spliterator",
- "java.util.Spliterator$OfDouble",
- "java.util.Spliterator$OfInt",
- "java.util.Spliterator$OfLong",
- "java.util.Spliterator$OfPrimitive",
- "java.util.function.BiConsumer",
- "java.util.function.BiFunction",
- "java.util.function.BiPredicate",
- "java.util.function.BinaryOperator",
- "java.util.function.Consumer",
- "java.util.function.DoubleBinaryOperator",
- "java.util.function.DoubleConsumer",
- "java.util.function.DoubleFunction",
- "java.util.function.DoublePredicate",
- "java.util.function.DoubleToIntFunction",
- "java.util.function.DoubleToLongFunction",
- "java.util.function.DoubleUnaryOperator",
- "java.util.function.Function",
- "java.util.function.IntBinaryOperator",
- "java.util.function.IntConsumer",
- "java.util.function.IntFunction",
- "java.util.function.IntPredicate",
- "java.util.function.IntToDoubleFunction",
- "java.util.function.IntToLongFunction",
- "java.util.function.IntUnaryOperator",
- "java.util.function.LongBinaryOperator",
- "java.util.function.LongConsumer",
- "java.util.function.LongFunction",
- "java.util.function.LongPredicate",
- "java.util.function.LongToDoubleFunction",
- "java.util.function.LongToIntFunction",
- "java.util.function.LongUnaryOperator",
- "java.util.function.ObjDoubleConsumer",
- "java.util.function.ObjIntConsumer",
- "java.util.function.ObjLongConsumer",
- "java.util.function.Predicate",
- "java.util.function.Supplier",
- "java.util.function.ToDoubleFunction",
- "java.util.function.ToIntFunction",
- "java.util.function.ToLongFunction",
- "java.util.function.UnaryOperator",
- "java.util.stream.BaseStream",
- "java.util.stream.Collector",
- "java.util.stream.DoubleStream",
- "java.util.stream.IntStream",
- "java.util.stream.LongStream",
- "java.util.stream.Stream"
- ]
- }
- ],
- "library_flags": [
- {
- "api_level_below_or_equal": 25,
- "rewrite_prefix": {
- "j$.time.": "java.time.",
- "java.time.": "j$.time.",
- "java.util.Desugar": "j$.util.Desugar"
- },
- "retarget_lib_member": {
- "java.util.Date#toInstant": "java.util.DesugarDate",
- "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar",
- "java.util.TimeZone#toZoneId": "java.util.DesugarTimeZone"
- },
- "custom_conversion": {
- "java.time.ZonedDateTime": "java.time.TimeConversions",
- "java.time.LocalDate": "java.time.TimeConversions",
- "java.time.Duration": "java.time.TimeConversions",
- "java.time.ZoneId": "java.time.TimeConversions",
- "java.time.MonthDay": "java.time.TimeConversions",
- "java.time.Instant": "java.time.TimeConversions"
- }
- },
- {
- "api_level_below_or_equal": 23,
- "rewrite_prefix": {
- "j$.util.Optional": "java.util.Optional",
- "j$.util.LongSummaryStatistics": "java.util.LongSummaryStatistics",
- "j$.util.IntSummaryStatistics": "java.util.IntSummaryStatistics",
- "j$.util.DoubleSummaryStatistics": "java.util.DoubleSummaryStatistics",
- "java.util.stream.": "j$.util.stream.",
- "java.util.function.": "j$.util.function.",
- "java.util.Comparators": "j$.util.Comparators",
- "java.util.DoubleSummaryStatistics": "j$.util.DoubleSummaryStatistics",
- "java.util.IntSummaryStatistics": "j$.util.IntSummaryStatistics",
- "java.util.LongSummaryStatistics": "j$.util.LongSummaryStatistics",
- "java.util.Objects": "j$.util.Objects",
- "java.util.Optional": "j$.util.Optional",
- "java.util.PrimitiveIterator": "j$.util.PrimitiveIterator",
- "java.util.SortedSet$1": "j$.util.SortedSet$1",
- "java.util.Spliterator": "j$.util.Spliterator",
- "java.util.StringJoiner": "j$.util.StringJoiner",
- "java.util.Tripwire": "j$.util.Tripwire",
- "java.util.concurrent.DesugarUnsafe": "j$.util.concurrent.DesugarUnsafe",
- "java.util.concurrent.ThreadLocalRandom": "j$.util.concurrent.ThreadLocalRandom",
- "java.util.concurrent.atomic.DesugarAtomic": "j$.util.concurrent.atomic.DesugarAtomic",
- "java.util.concurrent.ConcurrentHashMap": "j$.util.concurrent.ConcurrentHashMap",
- "java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
- "java.io.UncheckedIOException": "j$.io.UncheckedIOException"
- },
- "retarget_lib_member": {
- "java.util.Arrays#stream": "java.util.DesugarArrays",
- "java.util.Arrays#spliterator": "java.util.DesugarArrays",
- "java.util.LinkedHashSet#spliterator": "java.util.DesugarLinkedHashSet",
- "java.io.BufferedReader#lines": "java.io.DesugarBufferedReader"
- },
- "dont_rewrite": [
- "java.util.Iterator#remove"
- ],
- "emulate_interface": {
- "java.util.Map$Entry": "j$.util.Map$Entry",
- "java.util.Collection": "j$.util.Collection",
- "java.util.Map": "j$.util.Map",
- "java.util.Iterator": "j$.util.Iterator",
- "java.util.Comparator": "j$.util.Comparator",
- "java.util.List": "j$.util.List",
- "java.util.SortedSet": "j$.util.SortedSet",
- "java.util.Set": "j$.util.Set",
- "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
- },
- "custom_conversion": {
- "java.util.Optional": "java.util.OptionalConversions",
- "java.util.OptionalDouble": "java.util.OptionalConversions",
- "java.util.OptionalInt": "java.util.OptionalConversions",
- "java.util.OptionalLong": "java.util.OptionalConversions",
- "java.util.LongSummaryStatistics": "java.util.LongSummaryStatisticsConversions",
- "java.util.IntSummaryStatistics": "java.util.IntSummaryStatisticsConversions",
- "java.util.DoubleSummaryStatistics": "java.util.DoubleSummaryStatisticsConversions"
- }
- }
- ],
- "program_flags": [
- {
- "api_level_below_or_equal": 25,
- "rewrite_prefix": {
- "java.time.": "j$.time.",
- "java.util.Desugar": "j$.util.Desugar"
- },
- "retarget_lib_member": {
- "java.util.Calendar#toInstant": "java.util.DesugarCalendar",
- "java.util.Date#from": "java.util.DesugarDate",
- "java.util.Date#toInstant": "java.util.DesugarDate",
- "java.util.GregorianCalendar#from": "java.util.DesugarGregorianCalendar",
- "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar",
- "java.util.TimeZone#getTimeZone": "java.util.DesugarTimeZone",
- "java.util.TimeZone#toZoneId": "java.util.DesugarTimeZone"
- },
- "custom_conversion": {
- "java.time.ZonedDateTime": "java.time.TimeConversions",
- "java.time.LocalDate": "java.time.TimeConversions",
- "java.time.Duration": "java.time.TimeConversions",
- "java.time.ZoneId": "java.time.TimeConversions",
- "java.time.MonthDay": "java.time.TimeConversions",
- "java.time.Instant": "java.time.TimeConversions"
- }
- },
- {
- "api_level_below_or_equal": 23,
- "rewrite_prefix": {
- "java.util.stream.": "j$.util.stream.",
- "java.util.function.": "j$.util.function.",
- "java.util.DoubleSummaryStatistics": "j$.util.DoubleSummaryStatistics",
- "java.util.IntSummaryStatistics": "j$.util.IntSummaryStatistics",
- "java.util.LongSummaryStatistics": "j$.util.LongSummaryStatistics",
- "java.util.Objects": "j$.util.Objects",
- "java.util.Optional": "j$.util.Optional",
- "java.util.PrimitiveIterator": "j$.util.PrimitiveIterator",
- "java.util.Spliterator": "j$.util.Spliterator",
- "java.util.StringJoiner": "j$.util.StringJoiner",
- "java.util.concurrent.ThreadLocalRandom": "j$.util.concurrent.ThreadLocalRandom",
- "java.util.concurrent.atomic.DesugarAtomic": "j$.util.concurrent.atomic.DesugarAtomic",
- "java.util.concurrent.ConcurrentHashMap": "j$.util.concurrent.ConcurrentHashMap",
- "java.io.UncheckedIOException": "j$.io.UncheckedIOException"
- },
- "retarget_lib_member": {
- "java.util.Arrays#stream": "java.util.DesugarArrays",
- "java.util.Arrays#spliterator": "java.util.DesugarArrays",
- "java.util.LinkedHashSet#spliterator": "java.util.DesugarLinkedHashSet",
- "java.util.concurrent.atomic.AtomicInteger#getAndUpdate": "java.util.concurrent.atomic.DesugarAtomicInteger",
- "java.util.concurrent.atomic.AtomicInteger#updateAndGet": "java.util.concurrent.atomic.DesugarAtomicInteger",
- "java.util.concurrent.atomic.AtomicInteger#getAndAccumulate": "java.util.concurrent.atomic.DesugarAtomicInteger",
- "java.util.concurrent.atomic.AtomicInteger#accumulateAndGet": "java.util.concurrent.atomic.DesugarAtomicInteger",
- "java.util.concurrent.atomic.AtomicLong#getAndUpdate": "java.util.concurrent.atomic.DesugarAtomicLong",
- "java.util.concurrent.atomic.AtomicLong#updateAndGet": "java.util.concurrent.atomic.DesugarAtomicLong",
- "java.util.concurrent.atomic.AtomicLong#getAndAccumulate": "java.util.concurrent.atomic.DesugarAtomicLong",
- "java.util.concurrent.atomic.AtomicLong#accumulateAndGet": "java.util.concurrent.atomic.DesugarAtomicLong",
- "java.util.concurrent.atomic.AtomicReference#getAndUpdate": "java.util.concurrent.atomic.DesugarAtomicReference",
- "java.util.concurrent.atomic.AtomicReference#updateAndGet": "java.util.concurrent.atomic.DesugarAtomicReference",
- "java.util.concurrent.atomic.AtomicReference#getAndAccumulate": "java.util.concurrent.atomic.DesugarAtomicReference",
- "java.util.concurrent.atomic.AtomicReference#accumulateAndGet": "java.util.concurrent.atomic.DesugarAtomicReference",
- "java.util.Collections#synchronizedMap": "java.util.DesugarCollections",
- "java.util.Collections#synchronizedSortedMap": "java.util.DesugarCollections",
- "java.io.BufferedReader#lines": "java.io.DesugarBufferedReader"
- },
- "dont_rewrite": [
- "java.util.Iterator#remove"
- ],
- "emulate_interface": {
- "java.util.Map$Entry": "j$.util.Map$Entry",
- "java.util.Collection": "j$.util.Collection",
- "java.util.Map": "j$.util.Map",
- "java.util.Iterator": "j$.util.Iterator",
- "java.util.Comparator": "j$.util.Comparator",
- "java.util.List": "j$.util.List",
- "java.util.SortedSet": "j$.util.SortedSet",
- "java.util.Set": "j$.util.Set",
- "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
- },
- "custom_conversion": {
- "java.util.Optional": "java.util.OptionalConversions",
- "java.util.OptionalDouble": "java.util.OptionalConversions",
- "java.util.OptionalInt": "java.util.OptionalConversions",
- "java.util.OptionalLong": "java.util.OptionalConversions",
- "java.util.LongSummaryStatistics": "java.util.LongSummaryStatisticsConversions",
- "java.util.IntSummaryStatistics": "java.util.IntSummaryStatisticsConversions",
- "java.util.DoubleSummaryStatistics": "java.util.DoubleSummaryStatisticsConversions"
- }
- }
- ],
- "shrinker_config": [
- "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap$TreeBin { int lockState; }",
- "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap { int sizeCtl; int transferIndex; long baseCount; int cellsBusy; }",
- "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap$CounterCell { long value; }",
- "-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); public static final !synthetic <fields>; }",
- "-keeppackagenames j$",
- "-keepclassmembers class j$.util.IntSummaryStatistics { long count; long sum; int min; int max; }",
- "-keepclassmembers class j$.util.LongSummaryStatistics { long count; long sum; long min; long max; }",
- "-keepclassmembers class j$.util.DoubleSummaryStatistics { long count; double sum; double min; double max; }",
- "-keepattributes Signature",
- "-keepattributes EnclosingMethod",
- "-keepattributes InnerClasses",
- "-dontwarn sun.misc.Unsafe"
- ]
-}
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index 778274a..503352b 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -21,8 +21,12 @@
"retarget_method": {
"java.time.Instant java.util.Date#toInstant()": "java.util.DesugarDate",
"java.time.ZoneId java.util.TimeZone#toZoneId()": "java.util.DesugarTimeZone",
- "java.time.ZonedDateTime java.util.GregorianCalendar#toZonedDateTime()": "java.util.DesugarGregorianCalendar"
+ "java.time.ZonedDateTime java.util.GregorianCalendar#toZonedDateTime()": "java.util.DesugarGregorianCalendar",
+ "java.util.TimeZone java.util.TimeZone#getTimeZone(java.time.ZoneId)": "java.util.DesugarTimeZone"
},
+ "wrapper_conversion": [
+ "java.time.Clock"
+ ],
"custom_conversion": {
"java.time.Duration": "java.time.TimeConversions",
"java.time.Instant": "java.time.TimeConversions",
@@ -33,12 +37,6 @@
}
},
{
- "api_level_below_or_equal": 25,
- "wrapper_conversion": [
- "java.time.Clock"
- ]
- },
- {
"api_level_below_or_equal": 23,
"rewrite_prefix": {
"java.util.DoubleSummaryStatistics": "j$.util.DoubleSummaryStatistics",
@@ -154,6 +152,9 @@
"api_level_below_or_equal": 18,
"rewrite_prefix": {
"java.nio.charset.StandardCharsets": "j$.nio.charset.StandardCharsets"
+ },
+ "retarget_method": {
+ "boolean java.lang.Character#isBmpCodePoint(int)": "java.lang.DesugarCharacter"
}
}
],
@@ -164,8 +165,7 @@
"java.time.Instant java.util.Calendar#toInstant()": "java.util.DesugarCalendar",
"java.util.Date java.util.Date#from(java.time.Instant)": "java.util.DesugarDate",
"java.util.GregorianCalendar java.util.GregorianCalendar#from(java.time.ZonedDateTime)": "java.util.DesugarGregorianCalendar",
- "java.util.TimeZone java.util.TimeZone#getTimeZone(java.lang.String)": "java.util.DesugarTimeZone",
- "java.util.TimeZone java.util.TimeZone#getTimeZone(java.time.ZoneId)": "java.util.DesugarTimeZone"
+ "java.util.TimeZone java.util.TimeZone#getTimeZone(java.lang.String)": "java.util.DesugarTimeZone"
}
},
{
@@ -188,9 +188,15 @@
}
},
{
+ "api_level_below_or_equal": 19,
+ "dont_retarget": [
+ "android.support.multidex.MultiDexExtractor$ExtractedDex"
+ ]
+ },
+ {
"api_level_below_or_equal": 18,
- "retarget_method": {
- "boolean java.lang.Character#isBmpCodePoint(int)": "j$.lang.DesugarCharacter"
+ "rewrite_prefix": {
+ "java.lang.DesugarCharacter": "j$.lang.DesugarCharacter"
}
}
],
@@ -199,10 +205,21 @@
"api_level_below_or_equal": 10000,
"rewrite_prefix": {
"desugar.": "j$.desugar.",
+ "libcore.": "j$.libcore.",
"java.lang.Desugar": "j$.lang.Desugar",
"java.lang.ref.Cleaner": "j$.lang.ref.Cleaner",
- "libcore.": "j$.libcore.",
+ "wrapper." : "j$.wrapper.",
"sun.security.action.": "j$.sun.security.action."
+ },
+ "rewrite_derived_prefix": {
+ "java.io.": {
+ "__wrapper__.j$.io.": "j$.io.",
+ "__wrapper__.java.io.": "java.io."
+ },
+ "java.nio.": {
+ "__wrapper__.j$.nio.": "j$.nio.",
+ "__wrapper__.java.nio.": "java.nio."
+ }
}
},
{
@@ -223,7 +240,6 @@
"api_level_below_or_equal": 25,
"rewrite_prefix": {
"java.io.DesugarFile": "j$.io.DesugarFile",
- "java.nio.Desugar": "j$.nio.Desugar",
"java.nio.channels.AsynchronousChannel": "j$.nio.channels.AsynchronousChannel",
"java.nio.channels.AsynchronousFileChannel": "j$.nio.channels.AsynchronousFileChannel",
"java.nio.channels.CompletionHandler": "j$.nio.channels.CompletionHandler",
@@ -240,8 +256,7 @@
},
"retarget_method": {
"boolean java.util.Arrays#deepEquals0(java.lang.Object, java.lang.Object)": "java.util.DesugarArrays",
- "java.nio.file.Path java.io.File#toPath()": "java.io.DesugarFile",
- "java.util.TimeZone java.util.TimeZone#getTimeZone(java.time.ZoneId)": "java.util.DesugarTimeZone"
+ "java.nio.file.Path java.io.File#toPath()": "java.io.DesugarFile"
},
"backport": {
"java.lang.DesugarDouble": "java.lang.Double",
@@ -281,13 +296,13 @@
"java.util.Optional": {
"j$.util.Optional": "java.util.Optional"
}
- }
- },
- {
- "api_level_below_or_equal": 18,
+ },
"retarget_method": {
- "boolean java.lang.Character#isBmpCodePoint(int)": "java.lang.DesugarCharacter"
- }
+ "long java.io.InputStream#transferTo(java.io.OutputStream)": "java.io.DesugarInputStream"
+ },
+ "amend_library_method": [
+ "public long java.io.InputStream#transferTo(java.io.OutputStream)"
+ ]
}
],
"shrinker_config": [
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
index faf4817..ab3c8a6 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_alternative_3:2.0.0",
+ "identifier": "com.tools.android:desugar_jdk_libs_alternative_3:1.0.12",
"configuration_format_version": 100,
"required_compilation_api_level": 30,
"synthesized_library_classes_package_prefix": "j$.",
@@ -21,8 +21,12 @@
"retarget_method": {
"java.time.Instant java.util.Date#toInstant()": "java.util.DesugarDate",
"java.time.ZoneId java.util.TimeZone#toZoneId()": "java.util.DesugarTimeZone",
- "java.time.ZonedDateTime java.util.GregorianCalendar#toZonedDateTime()": "java.util.DesugarGregorianCalendar"
+ "java.time.ZonedDateTime java.util.GregorianCalendar#toZonedDateTime()": "java.util.DesugarGregorianCalendar",
+ "java.util.TimeZone java.util.TimeZone#getTimeZone(java.time.ZoneId)": "java.util.DesugarTimeZone"
},
+ "wrapper_conversion": [
+ "java.time.Clock"
+ ],
"custom_conversion": {
"java.time.Duration": "java.time.TimeConversions",
"java.time.Instant": "java.time.TimeConversions",
@@ -33,14 +37,9 @@
}
},
{
- "api_level_below_or_equal": 25,
- "wrapper_conversion": [
- "java.time.Clock"
- ]
- },
- {
"api_level_below_or_equal": 23,
"rewrite_prefix": {
+ "java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
"java.io.UncheckedIOException": "j$.io.UncheckedIOException",
"java.util.DoubleSummaryStatistics": "j$.util.DoubleSummaryStatistics",
"java.util.IntSummaryStatistics": "j$.util.IntSummaryStatistics",
@@ -97,15 +96,15 @@
"java.util.function.IntConsumer",
"java.util.function.IntBinaryOperator",
"java.util.function.UnaryOperator",
- "java.util.function.IntPredicate",
"java.util.function.DoubleConsumer",
+ "java.util.function.IntPredicate",
"java.util.Spliterator$OfLong",
"java.util.stream.Collector",
"java.util.function.LongPredicate",
"java.util.function.ToLongFunction",
"java.util.function.LongToDoubleFunction",
- "java.util.function.LongToIntFunction",
"java.util.PrimitiveIterator$OfInt",
+ "java.util.function.LongToIntFunction",
"java.util.function.Predicate",
"java.util.Spliterator$OfPrimitive",
"java.util.function.DoubleToIntFunction",
@@ -119,8 +118,8 @@
"java.util.Spliterator",
"java.util.stream.IntStream",
"java.util.function.LongBinaryOperator",
- "java.util.function.DoubleFunction",
"java.util.Spliterator$OfDouble",
+ "java.util.function.DoubleFunction",
"java.util.function.ObjIntConsumer",
"java.util.function.Function",
"java.util.function.Supplier",
@@ -131,8 +130,8 @@
"java.util.PrimitiveIterator$OfLong",
"java.util.function.BiConsumer",
"java.util.function.IntFunction",
- "java.util.function.IntToDoubleFunction",
"java.util.stream.LongStream",
+ "java.util.function.IntToDoubleFunction",
"java.util.function.LongFunction",
"java.util.function.ToIntFunction",
"java.util.function.LongConsumer",
@@ -157,6 +156,9 @@
"api_level_below_or_equal": 18,
"rewrite_prefix": {
"java.nio.charset.StandardCharsets": "j$.nio.charset.StandardCharsets"
+ },
+ "retarget_method": {
+ "boolean java.lang.Character#isBmpCodePoint(int)": "java.lang.DesugarCharacter"
}
}
],
@@ -167,8 +169,7 @@
"java.time.Instant java.util.Calendar#toInstant()": "java.util.DesugarCalendar",
"java.util.Date java.util.Date#from(java.time.Instant)": "java.util.DesugarDate",
"java.util.GregorianCalendar java.util.GregorianCalendar#from(java.time.ZonedDateTime)": "java.util.DesugarGregorianCalendar",
- "java.util.TimeZone java.util.TimeZone#getTimeZone(java.lang.String)": "java.util.DesugarTimeZone",
- "java.util.TimeZone java.util.TimeZone#getTimeZone(java.time.ZoneId)": "java.util.DesugarTimeZone"
+ "java.util.TimeZone java.util.TimeZone#getTimeZone(java.lang.String)": "java.util.DesugarTimeZone"
}
},
{
@@ -191,9 +192,15 @@
}
},
{
+ "api_level_below_or_equal": 19,
+ "dont_retarget": [
+ "android.support.multidex.MultiDexExtractor$ExtractedDex"
+ ]
+ },
+ {
"api_level_below_or_equal": 18,
- "retarget_method": {
- "boolean java.lang.Character#isBmpCodePoint(int)": "j$.lang.DesugarCharacter"
+ "rewrite_prefix": {
+ "java.lang.DesugarCharacter": "j$.lang.DesugarCharacter"
}
}
],
@@ -202,17 +209,41 @@
"api_level_below_or_equal": 10000,
"rewrite_prefix": {
"desugar.": "j$.desugar.",
+ "libcore.": "j$.libcore.",
"java.lang.Desugar": "j$.lang.Desugar",
"java.lang.ref.Cleaner": "j$.lang.ref.Cleaner",
- "libcore.": "j$.libcore.",
+ "wrapper." : "j$.wrapper.",
"sun.security.action.": "j$.sun.security.action."
+ },
+ "rewrite_derived_prefix": {
+ "java.io.": {
+ "__wrapper__.j$.io.": "j$.io.",
+ "__wrapper__.java.io.": "java.io."
+ },
+ "java.nio.": {
+ "__wrapper__.j$.nio.": "j$.nio.",
+ "__wrapper__.java.nio.": "java.nio."
+ }
}
},
{
"api_level_below_or_equal": 30,
+ "rewrite_derived_prefix": {
+ "java.time.": {
+ "j$.time.": "java.time."
+ }
+ }
+ },
+ {
+ "api_level_below_or_equal": 29,
+ "rewrite_prefix": {
+ "java.util.concurrent.Flow": "j$.util.concurrent.Flow"
+ }
+ },
+ {
+ "api_level_below_or_equal": 25,
"rewrite_prefix": {
"java.io.DesugarFile": "j$.io.DesugarFile",
- "java.nio.Desugar": "j$.nio.Desugar",
"java.nio.channels.AsynchronousChannel": "j$.nio.channels.AsynchronousChannel",
"java.nio.channels.AsynchronousFileChannel": "j$.nio.channels.AsynchronousFileChannel",
"java.nio.channels.CompletionHandler": "j$.nio.channels.CompletionHandler",
@@ -227,12 +258,8 @@
"sun.nio.fs.DynamicFileAttributeView": "j$.sun.nio.fs.DynamicFileAttributeView",
"sun.util.PreHashedMap": "j$.sun.util.PreHashedMap"
},
- "rewrite_derived_prefix": {
- "java.time.": {
- "j$.time.": "java.time."
- }
- },
"retarget_method": {
+ "boolean java.util.Arrays#deepEquals0(java.lang.Object, java.lang.Object)": "java.util.DesugarArrays",
"java.nio.file.Path java.io.File#toPath()": "java.io.DesugarFile"
},
"backport": {
@@ -240,18 +267,6 @@
"java.lang.DesugarInteger": "java.lang.Integer",
"java.lang.DesugarLong": "java.lang.Long",
"java.lang.DesugarMath": "java.lang.Math"
- }
- },
- {
- "api_level_below_or_equal": 29,
- "rewrite_prefix": {
- "java.util.concurrent.Flow": "j$.util.concurrent.Flow"
- }
- },
- {
- "api_level_below_or_equal": 25,
- "retarget_method": {
- "boolean java.util.Arrays#deepEquals0(java.lang.Object, java.lang.Object)": "java.util.DesugarArrays"
},
"amend_library_method": [
"private static boolean java.util.Arrays#deepEquals0(java.lang.Object, java.lang.Object)"
@@ -260,7 +275,6 @@
{
"api_level_below_or_equal": 23,
"rewrite_prefix": {
- "java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
"java.io.DesugarInputStream": "j$.io.DesugarInputStream",
"java.lang.FunctionalInterface": "j$.lang.FunctionalInterface",
"java.nio.channels.SeekableByteChannel": "j$.nio.channels.SeekableByteChannel",
@@ -286,18 +300,19 @@
"java.util.Optional": {
"j$.util.Optional": "java.util.Optional"
}
- }
- },
- {
- "api_level_below_or_equal": 18,
+ },
"retarget_method": {
- "boolean java.lang.Character#isBmpCodePoint(int)": "java.lang.DesugarCharacter"
- }
+ "long java.io.InputStream#transferTo(java.io.OutputStream)": "java.io.DesugarInputStream"
+ },
+ "amend_library_method": [
+ "public long java.io.InputStream#transferTo(java.io.OutputStream)"
+ ]
}
],
"shrinker_config": [
"-keepclassmembers class j$.util.concurrent.ConcurrentHashMap$TreeBin { int lockState; }",
"-keepclassmembers class j$.util.concurrent.ConcurrentHashMap { int sizeCtl; int transferIndex; long baseCount; int cellsBusy; }",
+ "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap { private void readObject(java.io.ObjectInputStream); private void writeObject(java.io.ObjectOutputStream); private void readObjectNoData(); private static final java.io.ObjectStreamField[] serialPersistentFields; private static final long serialVersionUID;}",
"-keepclassmembers class j$.util.concurrent.ConcurrentHashMap$CounterCell { long value; }",
"-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); public static final !synthetic <fields>; }",
"-keeppackagenames j$.**",
diff --git a/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java b/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
index 1ae2311..9c11062 100644
--- a/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
+++ b/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecificationParser;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
@@ -248,7 +248,7 @@
DesugaredLibrarySpecification getDesugaredLibraryConfiguration(DexItemFactory factory) {
if (desugaredLibrarySpecificationResources.isEmpty()) {
- return LegacyDesugaredLibrarySpecification.empty();
+ return HumanDesugaredLibrarySpecification.empty();
}
if (desugaredLibrarySpecificationResources.size() > 1) {
reporter.fatalError("Only one desugared library configuration is supported.");
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index a474a31..a522278 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.inspector.Inspector;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecificationParser;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
@@ -577,7 +577,7 @@
DesugaredLibrarySpecification getDesugaredLibraryConfiguration(
DexItemFactory factory, boolean libraryCompilation) {
if (desugaredLibrarySpecificationResources.isEmpty()) {
- return LegacyDesugaredLibrarySpecification.empty();
+ return HumanDesugaredLibrarySpecification.empty();
}
if (desugaredLibrarySpecificationResources.size() > 1) {
throw new CompilationError("Only one desugared library configuration is supported.");
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index bc6cb77..051565e 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -87,7 +87,7 @@
readDesugaredLibraryConfiguration(desugarConfigurationPath);
Path androidJarPath = getAndroidJarPath(specification.getRequiredCompilationApiLevel());
this.desugaredLibrarySpecification =
- specification.toMachineSpecification(options, androidJarPath);
+ specification.toMachineSpecification(options, androidJarPath, Timing.empty());
this.desugaredLibraryImplementation = Paths.get(desugarImplementationPath);
this.outputDirectory = Paths.get(outputDirectory);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index ac01496..732a73b 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -497,12 +497,14 @@
&& options.getProguardConfiguration().isOptimizing()) {
if (options.enableVerticalClassMerging) {
timing.begin("VerticalClassMerger");
- VerticalClassMerger verticalClassMerger =
+ VerticalClassMergerGraphLens lens =
new VerticalClassMerger(
- getDirectApp(appViewWithLiveness), appViewWithLiveness, executorService, timing);
- VerticalClassMergerGraphLens lens = verticalClassMerger.run();
+ getDirectApp(appViewWithLiveness),
+ appViewWithLiveness,
+ executorService,
+ timing)
+ .run();
if (lens != null) {
- appView.rewriteWithLens(lens);
runtimeTypeCheckInfo = runtimeTypeCheckInfo.rewriteWithLens(lens);
}
timing.end();
diff --git a/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java b/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
deleted file mode 100644
index 20571ba..0000000
--- a/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright (c) 2017, 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.benchmarks;
-
-import static com.android.tools.r8.benchmarks.BenchmarkUtils.printRuntimeNanoseconds;
-
-import com.android.tools.r8.ByteDataView;
-import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.D8;
-import com.android.tools.r8.D8Command;
-import com.android.tools.r8.D8Command.Builder;
-import com.android.tools.r8.DexFilePerClassFileConsumer;
-import com.android.tools.r8.DexFilePerClassFileConsumer.ForwardingConsumer;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.ProgramConsumer;
-import com.android.tools.r8.ProgramResource;
-import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.ResourceException;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.utils.DescriptorUtils;
-import com.android.tools.r8.utils.ThreadUtils;
-import com.android.tools.r8.utils.ZipUtils;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.ByteStreams;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-
-public class FrameworkIncrementalDexingBenchmark {
- private static final int ITERATIONS = 100;
- private static final int API = 24;
- private static final Path JAR_DESUGARED =
- Paths.get("third_party", "framework", "framework_14082017_desugared.jar");
- private static final Path JAR_NOT_DESUGARED =
- Paths.get("third_party", "framework", "framework_14082017.jar");
- private static final Path LIB =
- Paths.get("third_party", "android_jar", "lib-v" + API, "android.jar");
-
- static class InMemoryClassPathProvider implements ClassFileResourceProvider {
- Origin origin;
- Map<String, byte[]> resources;
-
- InMemoryClassPathProvider(Path archive) throws IOException {
- origin = new PathOrigin(archive);
- ImmutableMap.Builder<String, byte[]> builder = ImmutableMap.builder();
- ZipUtils.iter(
- archive.toString(),
- (entry, stream) -> {
- String name = entry.getName();
- if (ZipUtils.isClassFile(name)) {
- String descriptor = DescriptorUtils.guessTypeDescriptor(name);
- builder.put(descriptor, ByteStreams.toByteArray(stream));
- }
- });
- resources = builder.build();
- }
-
- @Override
- public Set<String> getClassDescriptors() {
- return resources.keySet();
- }
-
- @Override
- public ProgramResource getProgramResource(String descriptor) {
- byte[] bytes = resources.get(descriptor);
- return bytes == null
- ? null
- : ProgramResource.fromBytes(
- new EntryOrigin(descriptor, origin),
- Kind.CF,
- bytes,
- Collections.singleton(descriptor));
- }
- }
-
- static class EntryOrigin extends Origin {
- final String descriptor;
-
- public EntryOrigin(String descriptor, Origin parent) {
- super(parent);
- this.descriptor = descriptor;
- }
-
- @Override
- public String part() {
- return descriptor;
- }
- }
-
- private static String title(String title, boolean desugar) {
- return "FrameworkIncremental" + (desugar ? title : "NoDesugar" + title);
- }
-
- private static void compileAll(
- Path input,
- InMemoryClassPathProvider provider,
- boolean desugar,
- Map<String, ProgramResource> outputs,
- ExecutorService executor)
- throws IOException, CompilationFailedException {
-
- ProgramConsumer consumer =
- new DexFilePerClassFileConsumer.ForwardingConsumer(null) {
- @Override
- public synchronized void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- ProgramResource resource = ProgramResource.fromBytes(
- Origin.unknown(), Kind.DEX, data.copyByteData(), descriptors);
- for (String descriptor : descriptors) {
- assert !outputs.containsKey(descriptor);
- if (provider.resources.containsKey(descriptor)) {
- outputs.put(descriptor, resource);
- }
- }
- }
- };
-
- long start = System.nanoTime();
- D8.run(
- D8Command.builder()
- .setMinApiLevel(API)
- .setIntermediate(true)
- .setMode(CompilationMode.DEBUG)
- .addProgramFiles(input)
- .addLibraryFiles(LIB)
- .setDisableDesugaring(!desugar)
- .setProgramConsumer(consumer)
- .build(),
- executor);
- printRuntimeNanoseconds(title("DexAll", desugar), System.nanoTime() - start);
- }
-
- private static void compileGroupsOf(
- int count,
- List<String> descriptors,
- InMemoryClassPathProvider provider,
- boolean desugar,
- Map<String, ProgramResource> outputs,
- ExecutorService executor)
- throws IOException, CompilationFailedException {
- ProgramConsumer consumer =
- new ForwardingConsumer(null) {
- @Override
- public synchronized void accept(
- String primaryClassDescriptor,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- ProgramResource resource = ProgramResource.fromBytes(
- Origin.unknown(), Kind.DEX, data.copyByteData(), descriptors);
- for (String descriptor : descriptors) {
- if (provider.resources.containsKey(descriptor)) {
- outputs.put(descriptor, resource);
- }
- }
- }
- };
-
- descriptors.sort(String::compareTo);
- int increment = descriptors.size() / ITERATIONS;
- long start = System.nanoTime();
- for (int iteration = 0; iteration < ITERATIONS; iteration++) {
- int index = iteration * increment;
- Builder builder =
- D8Command.builder()
- .setMinApiLevel(API)
- .setIntermediate(true)
- .setMode(CompilationMode.DEBUG)
- .addClasspathResourceProvider(provider)
- .addLibraryFiles(LIB)
- .setProgramConsumer(consumer)
- .setDisableDesugaring(!desugar);
- for (int j = 0; j < count; j++) {
- builder.addClassProgramData(provider.resources.get(descriptors.get(index + j)),
- Origin.unknown());
- }
- D8.run(builder.build(), executor);
- }
- printRuntimeNanoseconds(title("DexGroupsOf" + count, desugar), System.nanoTime() - start);
- }
-
- private static void merge(
- boolean desugar, Map<String, ProgramResource> outputs, ExecutorService executor)
- throws IOException, CompilationFailedException, ResourceException {
- Builder builder =
- D8Command.builder()
- .setMinApiLevel(API)
- .setIntermediate(false)
- .setMode(CompilationMode.DEBUG)
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .setDisableDesugaring(true);
- for (ProgramResource input : outputs.values()) {
- try (InputStream inputStream = input.getByteStream()) {
- builder.addDexProgramData(ByteStreams.toByteArray(inputStream), input.getOrigin());
- }
- }
- long start = System.nanoTime();
- D8.run(
- builder // never need to desugar when merging dex.
- .build(),
- executor);
- printRuntimeNanoseconds(title("DexMerge", desugar), System.nanoTime() - start);
- }
-
- public static void main(String[] args)
- throws IOException, CompilationFailedException, ResourceException {
- boolean desugar = Arrays.asList(args).contains("--desugar");
- Path input = desugar ? JAR_NOT_DESUGARED : JAR_DESUGARED;
- InMemoryClassPathProvider provider = new InMemoryClassPathProvider(input);
- List<String> descriptors = new ArrayList<>(provider.getClassDescriptors());
- Map<String, ProgramResource> outputs = new HashMap<>(provider.getClassDescriptors().size());
- int threads = Integer.min(Runtime.getRuntime().availableProcessors(), 16) / 2;
- ExecutorService executor = ThreadUtils.getExecutorService(threads);
- try {
- compileAll(input, provider, desugar, outputs, executor);
- compileGroupsOf(1, descriptors, provider, desugar, outputs, executor);
- compileGroupsOf(10, descriptors, provider, desugar, outputs, executor);
- compileGroupsOf(100, descriptors, provider, desugar, outputs, executor);
- merge(desugar, outputs, executor);
- // TODO: We should run dex2oat to verify the compilation.
- } finally {
- executor.shutdown();
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/benchmarks/IncrementalDexingBenchmark.java b/src/main/java/com/android/tools/r8/benchmarks/IncrementalDexingBenchmark.java
deleted file mode 100644
index 477fd63..0000000
--- a/src/main/java/com/android/tools/r8/benchmarks/IncrementalDexingBenchmark.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2017, 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.benchmarks;
-
-import com.android.tools.r8.ByteDataView;
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.D8;
-import com.android.tools.r8.D8Command;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.utils.ThreadUtils;
-import java.io.IOException;
-import java.nio.file.Paths;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-
-public class IncrementalDexingBenchmark {
- private static final int ITERATIONS = 1000;
-
- public static void compile(ExecutorService executor)
- throws IOException, CompilationFailedException {
- D8.run(
- D8Command.builder()
- .addProgramFiles(Paths.get("build/test/examples/arithmetic.jar"))
- .setMode(CompilationMode.DEBUG)
- .setDisableDesugaring(true)
- .setProgramConsumer(
- new DexIndexedConsumer.ForwardingConsumer(null) {
- @Override
- public void accept(
- int fileIndex,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- if (fileIndex != 0) {
- throw new RuntimeException("WAT");
- }
- }
- })
- .build(),
- executor);
- }
-
- public static void main(String[] args) throws IOException, CompilationFailedException {
- int threads = Integer.min(Runtime.getRuntime().availableProcessors(), 16) / 2;
- ExecutorService executor = ThreadUtils.getExecutorService(threads);
- try {
- long start = System.nanoTime();
- for (int i = 0; i < ITERATIONS; i++) {
- compile(executor);
- }
- double elapsedMs = (System.nanoTime() - start) / 1000000.0;
- BenchmarkUtils.printRuntimeMilliseconds("IncrementalDexing", elapsedMs);
- } finally {
- executor.shutdown();
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java b/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java
index 524b6bc..fdfba1e 100644
--- a/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java
+++ b/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java
@@ -32,12 +32,7 @@
appView.setAppServices(AppServices.builder(appView).build());
for (DexProgramClass clazz : appView.appInfo().classes()) {
clazz.forEachProgramMethod(
- method ->
- method
- .getDefinition()
- .getCode()
- .asCfCode()
- .verifyFrames(method.getDefinition(), appView, clazz.getOrigin()));
+ method -> method.getDefinition().getCode().asCfCode().verifyFrames(method, appView));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index bf66099..efad6db 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -202,13 +202,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value1, value2 →
// ..., result
- FrameType frameType = FrameType.fromNumericType(type, factory);
+ FrameType frameType = FrameType.fromNumericType(type, dexItemFactory);
frameBuilder.popAndDiscard(frameType, frameType).push(frameType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
index 21e74a3..0af6a11 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -77,12 +77,13 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., arrayref →
// ..., length
- frameBuilder.popAndDiscardInitialized(factory.objectArrayType).push(factory.intType);
+ frameBuilder
+ .popAndDiscardInitialized(dexItemFactory.objectArrayType)
+ .push(dexItemFactory.intType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index 3385529..44f0e60 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -123,13 +123,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., arrayref, index →
// ..., value
- frameBuilder.popAndDiscardInitialized(factory.objectArrayType, factory.intType);
- frameBuilder.push(FrameType.fromMemberType(type, factory));
+ frameBuilder.popAndDiscardInitialized(dexItemFactory.objectArrayType, dexItemFactory.intType);
+ frameBuilder.push(FrameType.fromMemberType(type, dexItemFactory));
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index e4350e0..68d6b2d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -113,14 +113,13 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., arrayref, index, value →
// ...
frameBuilder
- .popAndDiscard(FrameType.fromMemberType(type, factory))
- .popAndDiscardInitialized(factory.objectArrayType, factory.intType);
+ .popAndDiscard(FrameType.fromMemberType(type, dexItemFactory))
+ .popAndDiscardInitialized(dexItemFactory.objectArrayType, dexItemFactory.intType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index 9e198e4..6098e98 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -127,12 +128,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., objectref →
// ..., objectref
- frameBuilder.popAndDiscardInitialized(factory.objectType).push(type);
+ frameBuilder.popAndDiscardInitialized(dexItemFactory.objectType).push(type);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
index e1a5ce5..c997da1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -127,13 +127,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value1, value2 →
// ..., result
- FrameType frameType = FrameType.fromNumericType(type, factory);
- frameBuilder.popAndDiscard(frameType, frameType).push(factory.intType);
+ FrameType frameType = FrameType.fromNumericType(type, dexItemFactory);
+ frameBuilder.popAndDiscard(frameType, frameType).push(dexItemFactory.intType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index 07cb6d2..c135288 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -146,12 +147,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(factory.classType);
+ frameBuilder.push(dexItemFactory.classType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
index f86c213..4efa8ae 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
@@ -221,12 +221,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(factory.classType);
+ frameBuilder.push(dexItemFactory.classType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
index b495441..5f5837a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
@@ -9,8 +9,8 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -98,12 +98,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(factory.methodHandleType);
+ frameBuilder.push(dexItemFactory.methodHandleType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
index 3578a70..3ef0e8d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
@@ -9,8 +9,8 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -96,12 +96,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(factory.methodTypeType);
+ frameBuilder.push(dexItemFactory.methodTypeType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
index f04dcfe..4d7dbb7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -69,10 +69,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
frameBuilder.push(DexItemFactory.nullValueType);
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index 759568d..ca9cdf0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -172,12 +172,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(type.toPrimitiveType().toDexType(factory));
+ frameBuilder.push(type.toPrimitiveType().toDexType(dexItemFactory));
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
index 9a079e7..1b46a48 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -99,12 +99,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(factory.stringType);
+ frameBuilder.push(dexItemFactory.stringType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
index 1958b5c..0a6887a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
@@ -10,8 +10,8 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexReference;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -118,12 +118,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., value
- frameBuilder.push(factory.stringType);
+ frameBuilder.push(dexItemFactory.stringType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
index 783a837..99c9151 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -183,10 +184,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
switch (opcode) {
case Opcodes.GETFIELD:
// ..., objectref →
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 47124c0..31bc71c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.CfCodeStackMapValidatingException;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -492,10 +493,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
frameBuilder.checkFrameAndSet(this);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrameVerificationHelper.java b/src/main/java/com/android/tools/r8/cf/code/CfFrameVerificationHelper.java
index 9272226..0d466f0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrameVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrameVerificationHelper.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.CfCodeStackMapValidatingException;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.utils.MapUtils;
import com.android.tools.r8.utils.collections.ImmutableDeque;
import com.android.tools.r8.utils.collections.ImmutableInt2ReferenceSortedMap;
@@ -40,7 +39,6 @@
private final BiPredicate<DexType, DexType> isJavaAssignable;
private final DexItemFactory factory;
private final List<CfTryCatch> tryCatchRanges;
- private final GraphLens graphLens;
private final int maxStackHeight;
private final Deque<CfTryCatch> currentCatchRanges = new ArrayDeque<>();
@@ -52,14 +50,12 @@
List<CfTryCatch> tryCatchRanges,
BiPredicate<DexType, DexType> isJavaAssignable,
DexItemFactory factory,
- GraphLens graphLens,
int maxStackHeight) {
this.context = context;
this.stateMap = stateMap;
this.tryCatchRanges = tryCatchRanges;
this.isJavaAssignable = isJavaAssignable;
this.factory = factory;
- this.graphLens = graphLens;
this.maxStackHeight = maxStackHeight;
throwStack = ImmutableDeque.of(FrameType.initialized(factory.throwableType));
// Compute all labels that marks a start or end to catch ranges.
@@ -113,6 +109,12 @@
return frameType;
}
+ public CfFrameVerificationHelper popAndDiscardInitialized(DexType expectedType) {
+ checkFrameIsSet();
+ popInitialized(expectedType);
+ return this;
+ }
+
public CfFrameVerificationHelper popAndDiscardInitialized(DexType... expectedTypes) {
checkFrameIsSet();
for (int i = expectedTypes.length - 1; i >= 0; i--) {
@@ -258,14 +260,14 @@
if (!source.isUninitializedThis()) {
return false;
}
- return target == factory.objectType || graphLens.lookupClassType(target) == context;
+ return target == factory.objectType || target == context;
}
public boolean isUninitializedNewAndTarget(FrameType source, DexType target) {
if (!source.isUninitializedNew()) {
return false;
}
- return target == factory.objectType || graphLens.lookupClassType(target) == context;
+ return target == factory.objectType || target == context;
}
public boolean isAssignableAndInitialized(FrameType source, DexType target) {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
index 6c434c4..eb82f47 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -94,10 +94,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
frameBuilder.checkTarget(target);
frameBuilder.setNoFrame();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index a3ad1cc..9db12ec 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -130,14 +130,15 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value →
// ...
frameBuilder.popAndDiscardInitialized(
- type.isObject() ? factory.objectType : type.toPrimitiveType().toDexType(factory));
+ type.isObject()
+ ? dexItemFactory.objectType
+ : type.toPrimitiveType().toDexType(dexItemFactory));
frameBuilder.checkTarget(target);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
index e42d7b2..2340a89 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -131,14 +132,15 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value1, value2 →
// ...
DexType type =
- this.type.isObject() ? factory.objectType : this.type.toPrimitiveType().toDexType(factory);
+ this.type.isObject()
+ ? dexItemFactory.objectType
+ : this.type.toPrimitiveType().toDexType(dexItemFactory);
frameBuilder.popAndDiscardInitialized(type, type);
frameBuilder.checkTarget(target);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
index ea9e810..735dde8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -91,10 +91,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
- frameBuilder.readLocal(var, factory.intType);
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
+ frameBuilder.readLocal(var, dexItemFactory.intType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
index 4d42276..1092bfe 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -111,12 +112,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., →
// ..., value
- frameBuilder.push(factory.intType);
+ frameBuilder.push(dexItemFactory.intType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
index 8b82246..0f93c4d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -121,12 +122,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., objectref →
// ..., result
- frameBuilder.popAndDiscardInitialized(factory.objectType).push(factory.intType);
+ frameBuilder.popAndDiscardInitialized(dexItemFactory.objectType).push(dexItemFactory.intType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index 4427f41..a1b7023 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -309,8 +309,7 @@
public abstract void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens);
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 292178b..9fb383a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -311,23 +311,24 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., objectref, [arg1, [arg2 ...]] →
// ... [ returnType ]
// OR, for static method calls:
// ..., [arg1, [arg2 ...]] →
// ...
- frameBuilder.popAndDiscardInitialized(this.method.proto.parameters.values);
- if (opcode == Opcodes.INVOKESPECIAL && method.isInstanceInitializer(factory)) {
- frameBuilder.popAndInitialize(context, method.holder);
+ frameBuilder.popAndDiscardInitialized(method.proto.parameters.values);
+ if (opcode == Opcodes.INVOKESPECIAL
+ && (method.isInstanceInitializer(dexItemFactory)
+ || method.mustBeInlinedIntoInstanceInitializer(appView))) {
+ frameBuilder.popAndInitialize(context.getHolderType(), method.holder);
} else if (opcode != Opcodes.INVOKESTATIC) {
frameBuilder.popInitialized(method.holder);
}
- if (this.method.proto.returnType != factory.voidType) {
- frameBuilder.push(this.method.proto.returnType);
+ if (!method.getReturnType().isVoidType()) {
+ frameBuilder.push(method.getReturnType());
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index 644ed7d..2082290 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
@@ -162,14 +163,13 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., [arg1, [arg2 ...]] →
// ...
frameBuilder.popAndDiscardInitialized(callSite.methodProto.parameters.values);
- if (callSite.methodProto.returnType != factory.voidType) {
+ if (callSite.methodProto.returnType != dexItemFactory.voidType) {
frameBuilder.push(callSite.methodProto.returnType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
index 0bff416..51829ec 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCodeStackMapValidatingException;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -80,10 +80,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// JSR/RET instructions cannot be verified since we have not type-checking way for addresses
// on the stack/locals. We have to abandon.
throw CfCodeStackMapValidatingException.error("Unexpected JSR/RET instruction");
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
index 028eff7..1f611b1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -92,10 +92,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// This is a no-op.
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
index 7aaf08c..4f9a4db 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -121,15 +121,16 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., objectref
frameBuilder.push(
frameBuilder.readLocal(
getLocalIndex(),
- type.isObject() ? factory.objectType : type.toPrimitiveType().toDexType(factory)));
+ type.isObject()
+ ? dexItemFactory.objectType
+ : type.toPrimitiveType().toDexType(dexItemFactory)));
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index 8a38898..71e31d8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -174,13 +174,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value1, value2 →
// ..., result
- FrameType value1Type = FrameType.fromNumericType(type, factory);
+ FrameType value1Type = FrameType.fromNumericType(type, dexItemFactory);
FrameType value2Type;
switch (opcode) {
case And:
@@ -189,7 +188,7 @@
value2Type = value1Type;
break;
default:
- value2Type = FrameType.initialized(factory.intType);
+ value2Type = FrameType.initialized(dexItemFactory.intType);
}
frameBuilder.popAndDiscard(value1Type, value2Type).push(value1Type);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
index 809317f..557d380 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -91,12 +91,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., objectref →
// ...
- frameBuilder.pop(FrameType.initialized(factory.objectType));
+ frameBuilder.pop(FrameType.initialized(dexItemFactory.objectType));
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index b798257..33fed6e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -124,14 +125,13 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., count1, [count2, ...] →
// ..., arrayref
for (int i = 0; i < dimensions; i++) {
- frameBuilder.popInitialized(factory.intType);
+ frameBuilder.popInitialized(dexItemFactory.intType);
}
frameBuilder.push(type);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
index e9a6518..a2621a8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -116,13 +116,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value →
// ..., result
- FrameType frameType = FrameType.fromNumericType(type, factory);
+ FrameType frameType = FrameType.fromNumericType(type, dexItemFactory);
frameBuilder.popAndDiscard(frameType).push(frameType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNew.java b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
index ff87575..95deb22 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -110,10 +111,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., objectref
frameBuilder.push(FrameType.uninitializedNew(new CfLabel(), type));
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
index 769fe22..50f82d0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -160,13 +161,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., count →
// ..., arrayref
assert type.isArrayType();
- frameBuilder.popAndDiscardInitialized(factory.intType).push(type);
+ frameBuilder.popAndDiscardInitialized(dexItemFactory.intType).push(type);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java b/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
index 335cce5..0d283d4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -113,10 +114,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ... →
// ..., objectref
frameBuilder.push(FrameType.initialized(type));
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNop.java b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
index c7be975..3518f2a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -73,10 +73,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// This is an actual Nop.
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
index 9e656f7..13c737d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -187,14 +187,13 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., value →
// ..., result
frameBuilder
- .popAndDiscard(FrameType.fromNumericType(from, factory))
- .push(FrameType.fromNumericType(to, factory));
+ .popAndDiscard(FrameType.fromNumericType(from, dexItemFactory))
+ .push(FrameType.fromNumericType(to, dexItemFactory));
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
index 0112d3f..e7bf24a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -106,10 +106,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// This is a no-op.
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java b/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
index b5b2275..ec9b7df 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -106,13 +106,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
for (DexField ignored : fields) {
- frameBuilder.popInitialized(factory.objectType);
+ frameBuilder.popInitialized(dexItemFactory.objectType);
}
- frameBuilder.push(factory.objectArrayType);
+ frameBuilder.push(dexItemFactory.objectArrayType);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index 9a74eaf..68038a4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -109,12 +109,11 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
- assert returnType != null;
- frameBuilder.popAndDiscardInitialized(returnType);
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
+ assert !context.getReturnType().isVoidType();
+ frameBuilder.popAndDiscardInitialized(context.getReturnType());
frameBuilder.setNoFrame();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
index 84a524d..9072b97 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -83,10 +83,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
frameBuilder.setNoFrame();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index 911141c..289846f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -350,10 +350,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
switch (opcode) {
case Pop:
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStore.java b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
index 9177bda..b096223 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -123,10 +123,9 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., ref →
// ...
FrameType pop = frameBuilder.pop();
@@ -134,7 +133,7 @@
case OBJECT:
frameBuilder.checkIsAssignable(
pop,
- factory.objectType,
+ dexItemFactory.objectType,
or(
frameBuilder::isUninitializedThisAndTarget,
frameBuilder::isUninitializedNewAndTarget,
@@ -143,25 +142,25 @@
return;
case INT:
frameBuilder.checkIsAssignable(
- pop, factory.intType, frameBuilder::isAssignableAndInitialized);
- frameBuilder.storeLocal(var, FrameType.initialized(factory.intType));
+ pop, dexItemFactory.intType, frameBuilder::isAssignableAndInitialized);
+ frameBuilder.storeLocal(var, FrameType.initialized(dexItemFactory.intType));
return;
case FLOAT:
frameBuilder.checkIsAssignable(
- pop, factory.floatType, frameBuilder::isAssignableAndInitialized);
- frameBuilder.storeLocal(var, FrameType.initialized(factory.floatType));
+ pop, dexItemFactory.floatType, frameBuilder::isAssignableAndInitialized);
+ frameBuilder.storeLocal(var, FrameType.initialized(dexItemFactory.floatType));
return;
case LONG:
frameBuilder.checkIsAssignable(
- pop, factory.longType, frameBuilder::isAssignableAndInitialized);
- frameBuilder.storeLocal(var, FrameType.initialized(factory.longType));
- frameBuilder.storeLocal(var + 1, FrameType.initialized(factory.longType));
+ pop, dexItemFactory.longType, frameBuilder::isAssignableAndInitialized);
+ frameBuilder.storeLocal(var, FrameType.initialized(dexItemFactory.longType));
+ frameBuilder.storeLocal(var + 1, FrameType.initialized(dexItemFactory.longType));
return;
case DOUBLE:
frameBuilder.checkIsAssignable(
- pop, factory.doubleType, frameBuilder::isAssignableAndInitialized);
- frameBuilder.storeLocal(var, FrameType.initialized(factory.doubleType));
- frameBuilder.storeLocal(var + 1, FrameType.initialized(factory.doubleType));
+ pop, dexItemFactory.doubleType, frameBuilder::isAssignableAndInitialized);
+ frameBuilder.storeLocal(var, FrameType.initialized(dexItemFactory.doubleType));
+ frameBuilder.storeLocal(var + 1, FrameType.initialized(dexItemFactory.doubleType));
return;
default:
throw new Unreachable("Unexpected type " + type);
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
index aef40c6..6321c35 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -144,13 +144,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., index/key →
// ...
- frameBuilder.popInitialized(factory.intType);
+ frameBuilder.popInitialized(dexItemFactory.intType);
frameBuilder.checkTarget(defaultTarget);
for (CfLabel target : targets) {
frameBuilder.checkTarget(target);
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
index b562faf..fc36a53 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -90,13 +90,12 @@
@Override
public void evaluate(
CfFrameVerificationHelper frameBuilder,
- DexType context,
- DexType returnType,
- DexItemFactory factory,
- InitClassLens initClassLens) {
+ DexMethod context,
+ AppView<?> appView,
+ DexItemFactory dexItemFactory) {
// ..., objectref →
// objectref
- frameBuilder.popInitialized(factory.throwableType);
+ frameBuilder.popInitialized(dexItemFactory.throwableType);
// The exception edges are verified in CfCode since this is a throwing instruction.
frameBuilder.setNoFrame();
}
diff --git a/src/main/java/com/android/tools/r8/debuginfo/DebugRepresentation.java b/src/main/java/com/android/tools/r8/debuginfo/DebugRepresentation.java
new file mode 100644
index 0000000..7a33b3c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/debuginfo/DebugRepresentation.java
@@ -0,0 +1,291 @@
+// Copyright (c) 2022, 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.debuginfo;
+
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.dex.VirtualFile;
+import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexDebugInfo;
+import com.android.tools.r8.graph.DexDebugInfo.PcBasedDebugInfo;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.LebUtils;
+import com.android.tools.r8.utils.LineNumberOptimizer;
+import com.android.tools.r8.utils.StringUtils;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
+import it.unimi.dsi.fastutil.ints.IntIterators;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DebugRepresentation {
+
+ public interface DebugRepresentationPredicate {
+
+ boolean useDexPcEncoding(DexProgramClass holder, DexEncodedMethod method);
+ }
+
+ public static DebugRepresentationPredicate none(InternalOptions options) {
+ assert !options.canUseDexPc2PcAsDebugInformation();
+ return (holder, method) -> false;
+ }
+
+ public static DebugRepresentationPredicate fromFiles(
+ List<VirtualFile> files, InternalOptions options) {
+ if (!options.canUseDexPc2PcAsDebugInformation()) {
+ return none(options);
+ }
+ if (options.canUseNativeDexPcInsteadOfDebugInfo() || options.testing.forcePcBasedEncoding) {
+ return (holder, method) -> true;
+ }
+ // TODO(b/220999985): Avoid the need to maintain a class-to-file map.
+ Map<DexProgramClass, VirtualFile> classMapping = new IdentityHashMap<>();
+ for (VirtualFile file : files) {
+ file.classes().forEach(c -> classMapping.put(c, file));
+ }
+ return (holder, method) -> {
+ if (!isPcCandidate(method)) {
+ return false;
+ }
+ VirtualFile file = classMapping.get(holder);
+ DebugRepresentation cutoffs = file.getDebugRepresentation();
+ return cutoffs.usesPcEncoding(method);
+ };
+ }
+
+ private final Int2ReferenceMap<CostSummary> paramToInfo;
+
+ private DebugRepresentation(Int2ReferenceMap<CostSummary> paramToInfo) {
+ this.paramToInfo = paramToInfo;
+ }
+
+ public static void computeForFile(
+ VirtualFile file, GraphLens graphLens, NamingLens namingLens, InternalOptions options) {
+ if (!options.canUseDexPc2PcAsDebugInformation()
+ || options.canUseNativeDexPcInsteadOfDebugInfo()
+ || options.testing.forcePcBasedEncoding) {
+ return;
+ }
+ // First collect all of the per-pc costs
+ // (the sum of the normal debug info for all methods sharing the same max pc and param count.)
+ Int2ReferenceMap<CostSummary> paramCountToCosts = new Int2ReferenceOpenHashMap<>();
+ for (DexProgramClass clazz : file.classes()) {
+ IdentityHashMap<DexString, List<DexEncodedMethod>> overloads =
+ LineNumberOptimizer.groupMethodsByRenamedName(graphLens, namingLens, clazz);
+ for (List<DexEncodedMethod> methods : overloads.values()) {
+ if (methods.size() != 1) {
+ // Never use PC info for overloaded methods. They need distinct lines to disambiguate.
+ continue;
+ }
+ DexEncodedMethod method = methods.get(0);
+ if (!isPcCandidate(method)) {
+ continue;
+ }
+ DexCode code = method.getCode().asDexCode();
+ DexDebugInfo debugInfo = code.getDebugInfo();
+ Instruction lastInstruction = getLastExecutableInstruction(code);
+ if (lastInstruction == null) {
+ continue;
+ }
+ int lastPc = lastInstruction.getOffset();
+ int debugInfoCost = estimatedDebugInfoSize(debugInfo);
+ paramCountToCosts
+ .computeIfAbsent(debugInfo.getParameterCount(), DebugRepresentation.CostSummary::new)
+ .addCost(lastPc, debugInfoCost);
+ }
+ }
+ // Second compute the cost of converting to a pc encoding.
+ paramCountToCosts.forEach((ignored, summary) -> summary.computeConversionCosts());
+ // The result is stored on the virtual files for thread safety.
+ // TODO(b/220999985): Consider just passing this to the line number optimizer once fixed.
+ file.setDebugRepresentation(new DebugRepresentation(paramCountToCosts));
+ }
+
+ private boolean usesPcEncoding(DexEncodedMethod method) {
+ DexCode code = method.getCode().asDexCode();
+ DexDebugInfo debugInfo = code.getDebugInfo();
+ int paramCount = debugInfo.getParameterCount();
+ CostSummary conversionInfo = paramToInfo.get(paramCount);
+ if (conversionInfo.cutoff < 0) {
+ return false;
+ }
+ Instruction lastInstruction = getLastExecutableInstruction(code);
+ if (lastInstruction == null) {
+ return false;
+ }
+ int maxPc = lastInstruction.getOffset();
+ return maxPc <= conversionInfo.cutoff;
+ }
+
+ @Override
+ public String toString() {
+ List<CostSummary> sorted = new ArrayList<>(paramToInfo.values());
+ sorted.sort(Comparator.comparing(i -> i.paramCount));
+ return StringUtils.join("\n", sorted, CostSummary::toString);
+ }
+
+ private static boolean isPcCandidate(DexEncodedMethod method) {
+ if (!method.hasCode() || !method.getCode().isDexCode()) {
+ return false;
+ }
+ DexCode code = method.getCode().asDexCode();
+ return LineNumberOptimizer.doesContainPositions(code);
+ }
+
+ /** The cost of representing normal debug info for all methods with this max pc value. */
+ private static class PcNormalCost {
+
+ final int pc;
+ int cost;
+ int methods;
+
+ public PcNormalCost(int pc) {
+ assert pc >= 0;
+ this.pc = pc;
+ }
+
+ void add(int cost) {
+ assert cost >= 0;
+ methods++;
+ this.cost += cost;
+ }
+ }
+
+ /** The summary of normal costs for all debug info with a particular parameter size. */
+ private static class CostSummary {
+
+ private final int paramCount;
+
+ // Values for the normal encoding costs per-pc.
+ private final Int2ReferenceMap<PcNormalCost> pcToCost = new Int2ReferenceOpenHashMap<>();
+ private int minPc = Integer.MAX_VALUE;
+ private int maxPc = Integer.MIN_VALUE;
+
+ // Values for the conversion costs. These are computed only after all per-pc costs are known.
+ private int cutoff;
+ private int normalPreCutoffCost;
+ private int normalPostCutoffCost;
+
+ private CostSummary(int paramCount) {
+ assert paramCount >= 0;
+ this.paramCount = paramCount;
+ }
+
+ private void addCost(int pc, int cost) {
+ assert pc >= 0;
+ pcToCost.computeIfAbsent(pc, PcNormalCost::new).add(cost);
+ minPc = Math.min(minPc, pc);
+ maxPc = Math.max(maxPc, pc);
+ }
+
+ private void computeConversionCosts() {
+ assert !pcToCost.isEmpty();
+ // Point at which it is estimated that conversion to PC-encoding is viable.
+ int currentConvertedPc = -1;
+ // The normal cost of the part that is viable for conversion (this is just for debugging).
+ int normalConvertedCost = 0;
+ // The normal cost of the part that is not yet part of the converted range.
+ int normalOutstandingCost = 0;
+ // Iterate in ascending order as the point conversion cost is the sum of the preceding costs.
+ int[] sortedPcs = new int[pcToCost.size()];
+ IntIterators.unwrap(pcToCost.keySet().iterator(), sortedPcs);
+ Arrays.sort(sortedPcs);
+ for (int currentPc : sortedPcs) {
+ PcNormalCost pcSummary = pcToCost.get(currentPc);
+ // The cost of the debug info unconverted is the sum of the unconverted up to this point.
+ normalOutstandingCost += pcSummary.cost;
+ // The cost of the conversion is the delta between the already converted and the current.
+ // This does not account for the header overhead on converting the first point. However,
+ // the few bytes overhead per param-count should not affect much.
+ int costToConvert = currentPc - currentConvertedPc;
+ // If the estimated cost is larger we convert. The order here could be either way as
+ // both the normal cost and converted cost are estimates. Canonicalization could reduce
+ // the former and compaction could reduce the latter.
+ if (normalOutstandingCost > costToConvert) {
+ normalConvertedCost += normalOutstandingCost;
+ normalOutstandingCost = 0;
+ currentConvertedPc = currentPc;
+ }
+ }
+ cutoff = currentConvertedPc;
+ normalPreCutoffCost = normalConvertedCost;
+ normalPostCutoffCost = normalOutstandingCost;
+ assert cutoff >= -1;
+ assert normalPreCutoffCost >= 0;
+ assert normalPostCutoffCost >= 0;
+ assert preCutoffPcCost() >= 0;
+ assert postCutoffPcCost() >= 0;
+ }
+
+ private int preCutoffPcCost() {
+ return cutoff > 0 ? PcBasedDebugInfo.estimatedWriteSize(paramCount, cutoff) : 0;
+ }
+
+ private int postCutoffPcCost() {
+ return cutoff < maxPc ? PcBasedDebugInfo.estimatedWriteSize(paramCount, maxPc - cutoff) : 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("p:")
+ .append(paramCount)
+ .append(", c:")
+ .append(cutoff)
+ .append(", m:")
+ .append(maxPc);
+ if (cutoff > 0) {
+ builder
+ .append(", preCutNormal:")
+ .append(normalPreCutoffCost)
+ .append(", preCutPC:")
+ .append(preCutoffPcCost());
+ }
+ if (cutoff < maxPc) {
+ builder
+ .append(", postCutNormal:")
+ .append(normalPostCutoffCost)
+ .append(", postCutPC:")
+ .append(postCutoffPcCost());
+ }
+ return builder.toString();
+ }
+ }
+
+ private static Instruction getLastExecutableInstruction(DexCode code) {
+ Instruction lastInstruction = null;
+ for (Instruction instruction : code.instructions) {
+ if (!instruction.isPayload()) {
+ lastInstruction = instruction;
+ }
+ }
+ return lastInstruction;
+ }
+
+ private static int estimatedDebugInfoSize(DexDebugInfo info) {
+ if (info.isPcBasedInfo()) {
+ return info.asPcBasedInfo().estimatedWriteSize();
+ }
+ // Each event is a single byte so we take the event length as the cost of the info.
+ // Note that the line number optimizer could reduce the line diffs such that deltas are
+ // smaller, but this is likely a very good estimate of the actual cost.
+ int parameterCount = info.getParameterCount();
+ int eventCount = info.asEventBasedInfo().events.length;
+ // Size: startline(0) + paramCount + null-array[paramCount] + eventCount + 1(end-event)
+ return LebUtils.sizeAsUleb128(0)
+ + LebUtils.sizeAsUleb128(parameterCount)
+ + LebUtils.sizeAsUleb128(0) * parameterCount
+ + eventCount
+ + 1;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 1eb78d1..0705b78 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -17,6 +17,8 @@
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.SourceFileEnvironment;
+import com.android.tools.r8.debuginfo.DebugRepresentation;
+import com.android.tools.r8.debuginfo.DebugRepresentation.DebugRepresentationPredicate;
import com.android.tools.r8.dex.FileWriter.ByteBufferResult;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.features.FeatureSplitConfiguration.DataResourceProvidersAndConsumer;
@@ -295,6 +297,7 @@
Timing fileTiming = Timing.create("VirtualFile " + virtualFile.getId(), options);
computeOffsetMappingAndRewriteJumboStrings(
virtualFile, lazyDexStrings, fileTiming);
+ DebugRepresentation.computeForFile(virtualFile, graphLens, namingLens, options);
fileTiming.end();
return fileTiming;
},
@@ -303,10 +306,15 @@
merger.end();
}
+
// Now code offsets are fixed, compute the mapping file content.
if (willComputeProguardMap()) {
+ // TODO(b/220999985): Refactor line number optimization to be per file and thread it above.
+ DebugRepresentationPredicate representation =
+ DebugRepresentation.fromFiles(virtualFiles, options);
delayedProguardMapId.set(
- runAndWriteMap(inputApp, appView, namingLens, timing, originalSourceFiles));
+ runAndWriteMap(
+ inputApp, appView, namingLens, timing, originalSourceFiles, representation));
}
// With the mapping id/hash known, it is safe to compute the remaining dex strings.
diff --git a/src/main/java/com/android/tools/r8/dex/Constants.java b/src/main/java/com/android/tools/r8/dex/Constants.java
index 8ea7319..7cf3ca9 100644
--- a/src/main/java/com/android/tools/r8/dex/Constants.java
+++ b/src/main/java/com/android/tools/r8/dex/Constants.java
@@ -142,6 +142,7 @@
public static final String INSTANCE_INITIALIZER_NAME = "<init>";
public static final String CLASS_INITIALIZER_NAME = "<clinit>";
public static final String TEMPORARY_INSTANCE_INITIALIZER_PREFIX = "$r8$constructor";
+ public static final String SYNTHETIC_INSTANCE_INITIALIZER_PREFIX = "$r8$init$synthetic";
public static final int MAX_NON_JUMBO_INDEX = U16BIT_MAX;
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index e7c7a1d..a085223 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import com.android.tools.r8.FeatureSplit;
+import com.android.tools.r8.debuginfo.DebugRepresentation;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
@@ -59,16 +60,6 @@
public class VirtualFile {
- // The fill strategy determine how to distribute classes into dex files.
- enum FillStrategy {
- // Distribute classes in as few dex files as possible filling each dex file as much as possible.
- FILL_MAX,
- // Distribute classes keeping some space for future growth. This is mainly useful together with
- // the package map distribution.
- LEAVE_SPACE_FOR_GROWTH,
- // TODO(sgjesse): Does "minimal main dex" combined with "leave space for growth" make sense?
- }
-
public static final int MAX_ENTRIES = Constants.U16BIT_MAX + 1;
/**
@@ -83,6 +74,7 @@
private final FeatureSplit featureSplit;
private final DexProgramClass primaryClass;
+ private DebugRepresentation debugRepresentation;
VirtualFile(
int id,
@@ -150,6 +142,17 @@
return primaryClass == null ? null : primaryClass.type.descriptor.toString();
}
+ public void setDebugRepresentation(DebugRepresentation debugRepresentation) {
+ assert debugRepresentation != null;
+ assert this.debugRepresentation == null;
+ this.debugRepresentation = debugRepresentation;
+ }
+
+ public DebugRepresentation getDebugRepresentation() {
+ assert debugRepresentation != null;
+ return debugRepresentation;
+ }
+
public static String deriveCommonPrefixAndSanityCheck(List<String> fileNames) {
Iterator<String> nameIterator = fileNames.iterator();
String first = nameIterator.next();
@@ -278,8 +281,8 @@
hasMainDexList, transaction.getNumberOfMethods(), transaction.getNumberOfFields()));
}
- private boolean isFilledEnough(FillStrategy fillStrategy) {
- return isFull(fillStrategy == FillStrategy.FILL_MAX ? MAX_ENTRIES : MAX_PREFILL_ENTRIES);
+ private boolean isFilledEnough() {
+ return isFull(MAX_ENTRIES);
}
public void abortTransaction() {
@@ -492,12 +495,6 @@
protected void addFeatureSplitFiles(Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses)
throws IOException {
- addFeatureSplitFiles(featureSplitClasses, FillStrategy.FILL_MAX);
- }
-
- protected void addFeatureSplitFiles(
- Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses, FillStrategy fillStrategy)
- throws IOException {
if (featureSplitClasses.isEmpty()) {
return;
}
@@ -524,7 +521,6 @@
appView,
featureClasses,
originalNames,
- fillStrategy,
0,
writer.graphLens,
writer.initClassLens,
@@ -536,13 +532,11 @@
}
public static class FillFilesDistributor extends DistributorBase {
- private final FillStrategy fillStrategy;
private final ExecutorService executorService;
FillFilesDistributor(ApplicationWriter writer, InternalOptions options,
ExecutorService executorService) {
super(writer, options);
- this.fillStrategy = FillStrategy.FILL_MAX;
this.executorService = executorService;
}
@@ -594,7 +588,6 @@
appView,
classes,
originalNames,
- fillStrategy,
fileIndexOffset,
writer.graphLens,
writer.initClassLens,
@@ -602,7 +595,7 @@
options)
.call();
}
- addFeatureSplitFiles(featureSplitClasses, fillStrategy);
+ addFeatureSplitFiles(featureSplitClasses);
assert totalClassNumber == virtualFiles.stream().mapToInt(dex -> dex.classes().size()).sum();
return virtualFiles;
@@ -1028,7 +1021,6 @@
private final List<DexProgramClass> classes;
private final Map<DexProgramClass, String> originalNames;
private final DexItemFactory dexItemFactory;
- private final FillStrategy fillStrategy;
private final InternalOptions options;
private final VirtualFileCycler cycler;
@@ -1037,7 +1029,6 @@
AppView<?> appView,
Set<DexProgramClass> classes,
Map<DexProgramClass, String> originalNames,
- FillStrategy fillStrategy,
int fileIndexOffset,
GraphLens graphLens,
InitClassLens initClassLens,
@@ -1046,7 +1037,6 @@
this.classes = new ArrayList<>(classes);
this.originalNames = originalNames;
this.dexItemFactory = appView.dexItemFactory();
- this.fillStrategy = fillStrategy;
this.options = options;
this.cycler =
new VirtualFileCycler(
@@ -1170,7 +1160,7 @@
&& current.getNumberOfClasses() > options.testing.limitNumberOfClassesPerDex) {
return true;
}
- return current.isFilledEnough(fillStrategy) || current.isFull();
+ return current.isFull();
}
private void addNonPackageClasses(
@@ -1179,7 +1169,7 @@
VirtualFile current;
current = cycler.next();
for (DexProgramClass clazz : nonPackageClasses) {
- if (current.isFilledEnough(fillStrategy)) {
+ if (current.isFull()) {
current = getVirtualFile(cycler);
}
current.addClass(clazz);
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index cbf79f2..6f1ab90 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -433,7 +433,7 @@
return codeLens;
}
- private void setCodeLens(GraphLens codeLens) {
+ public void setCodeLens(GraphLens codeLens) {
this.codeLens = codeLens;
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 9ab5faa..4358a27 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -25,8 +25,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeInstructionMetadata;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadata;
-import com.android.tools.r8.graph.proto.ArgumentInfo;
-import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.MemberType;
@@ -34,6 +32,7 @@
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.conversion.CfSourceCode;
+import com.android.tools.r8.ir.conversion.ExtraParameter;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -404,8 +403,7 @@
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
GraphLens graphLens = appView.graphLens();
- assert verifyFrames(method.getDefinition(), appView, null).isValid()
- : "Could not validate stack map frames";
+ assert verifyFrames(method, appView).isValid() : "Could not validate stack map frames";
DexItemFactory dexItemFactory = appView.dexItemFactory();
InitClassLens initClassLens = appView.initClassLens();
InternalOptions options = appView.options();
@@ -506,8 +504,7 @@
@Override
public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
- verifyFramesOrRemove(
- method.getDefinition(), appView, origin, IRBuilder.lookupPrototypeChanges(appView, method));
+ verifyFramesOrRemove(method, appView, getCodeLens(appView));
return internalBuildPossiblyWithLocals(
method, method, appView, appView.codeLens(), null, null, origin, null);
}
@@ -525,7 +522,7 @@
assert valueNumberGenerator != null;
assert callerPosition != null;
assert protoChanges != null;
- verifyFramesOrRemove(method.getDefinition(), appView, origin, protoChanges);
+ verifyFramesOrRemove(method, appView, codeLens);
return internalBuildPossiblyWithLocals(
context,
method,
@@ -537,12 +534,8 @@
protoChanges);
}
- private void verifyFramesOrRemove(
- DexEncodedMethod method,
- AppView<?> appView,
- Origin origin,
- RewrittenPrototypeDescription protoChanges) {
- stackMapStatus = verifyFrames(method, appView, origin, protoChanges);
+ private void verifyFramesOrRemove(ProgramMethod method, AppView<?> appView, GraphLens codeLens) {
+ stackMapStatus = verifyFrames(method, appView, codeLens);
if (!stackMapStatus.isValid()) {
ArrayList<CfInstruction> copy = new ArrayList<>(instructions);
copy.removeIf(CfInstruction::isFrame);
@@ -874,30 +867,31 @@
originalHolder, maxStack, maxLocals, newInstructions, tryCatchRanges, localVariables);
}
- public StackMapStatus verifyFrames(DexEncodedMethod method, AppView<?> appView, Origin origin) {
- return verifyFrames(method, appView, origin, RewrittenPrototypeDescription.none());
+ public StackMapStatus verifyFrames(ProgramMethod method, AppView<?> appView) {
+ return verifyFrames(method, appView, getCodeLens(appView));
}
- public StackMapStatus verifyFrames(
- DexEncodedMethod method,
- AppView<?> appView,
- Origin origin,
- RewrittenPrototypeDescription protoChanges) {
+ public StackMapStatus verifyFrames(ProgramMethod method, AppView<?> appView, GraphLens codeLens) {
+ GraphLens graphLens = appView.graphLens();
+ DexEncodedMethod definition = method.getDefinition();
if (!appView.options().canUseInputStackMaps()
|| appView.options().testing.disableStackMapVerification) {
return StackMapStatus.NOT_PRESENT;
}
- if (method.hasClassFileVersion() && method.getClassFileVersion().isLessThan(CfVersion.V1_7)) {
+ if (definition.hasClassFileVersion()
+ && definition.getClassFileVersion().isLessThan(CfVersion.V1_7)) {
return StackMapStatus.NOT_PRESENT;
}
- if (!method.isInstanceInitializer()
- && appView
- .graphLens()
- .getOriginalMethodSignature(method.getReference())
- .isInstanceInitializer(appView.dexItemFactory())) {
- // We cannot verify instance initializers if they are moved.
- return StackMapStatus.NOT_PRESENT;
- }
+
+ RewrittenPrototypeDescription protoChanges =
+ graphLens.lookupPrototypeChangesForMethodDefinition(method.getReference(), codeLens);
+
+ DexMethod previousMethodSignature =
+ graphLens.getOriginalMethodSignature(method.getReference(), codeLens);
+ boolean previousMethodSignatureIsInstance =
+ method.getDefinition().isInstance()
+ || protoChanges.getArgumentInfoCollection().isConvertedToStaticMethod();
+
// Build a map from labels to frames.
Map<CfLabel, CfFrame> stateMap = new IdentityHashMap<>();
List<CfLabel> labels = new ArrayList<>();
@@ -909,10 +903,7 @@
for (CfLabel label : labels) {
if (stateMap.containsKey(label)) {
return reportStackMapError(
- CfCodeStackMapValidatingException.multipleFramesForLabel(
- origin,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- appView),
+ CfCodeStackMapValidatingException.multipleFramesForLabel(method, appView),
appView);
}
stateMap.put(label, frame);
@@ -920,11 +911,7 @@
} else if (instruction != instructions.get(0)) {
// From b/168212806, it is possible that the first instruction is a frame.
return reportStackMapError(
- CfCodeStackMapValidatingException.unexpectedStackMapFrame(
- origin,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- appView),
- appView);
+ CfCodeStackMapValidatingException.unexpectedStackMapFrame(method, appView), appView);
}
}
// We are trying to map a frame to a label, but we can have positions in between, so skip
@@ -943,32 +930,28 @@
// If there are no frames but we have seen a jump instruction, we cannot verify the stack map.
if (requireStackMapFrame && stateMap.isEmpty()) {
return reportStackMapError(
- CfCodeStackMapValidatingException.noFramesForMethodWithJumps(
- origin,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- appView),
- appView);
- }
- DexType context = appView.graphLens().lookupType(method.getHolderType());
- DexType returnType = appView.graphLens().lookupType(method.getReference().getReturnType());
- if (!protoChanges.isEmpty() && protoChanges.getRewrittenReturnInfo() != null) {
- returnType = protoChanges.getRewrittenReturnInfo().getOldType();
+ CfCodeStackMapValidatingException.noFramesForMethodWithJumps(method, appView), appView);
}
CfFrameVerificationHelper builder =
new CfFrameVerificationHelper(
- context,
+ previousMethodSignature.getHolderType(),
stateMap,
tryCatchRanges,
isAssignablePredicate(appView),
appView.dexItemFactory(),
- appView.graphLens(),
maxStack);
if (stateMap.containsKey(null)) {
assert !shouldComputeInitialFrame();
builder.checkFrameAndSet(stateMap.get(null));
} else if (shouldComputeInitialFrame()) {
builder.checkFrameAndSet(
- new CfFrame(computeInitialLocals(context, method, protoChanges), new ArrayDeque<>()));
+ new CfFrame(
+ computeInitialLocals(
+ appView,
+ previousMethodSignature,
+ previousMethodSignatureIsInstance,
+ protoChanges),
+ new ArrayDeque<>()));
}
for (int i = 0; i < instructions.size(); i++) {
CfInstruction instruction = instructions.get(i);
@@ -980,17 +963,11 @@
assert !instruction.isStore();
builder.checkExceptionEdges();
}
- instruction.evaluate(
- builder, context, returnType, appView.dexItemFactory(), appView.initClassLens());
+ instruction.evaluate(builder, previousMethodSignature, appView, appView.dexItemFactory());
} catch (CfCodeStackMapValidatingException ex) {
return reportStackMapError(
CfCodeStackMapValidatingException.toDiagnostics(
- origin,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- i,
- instruction,
- ex.getMessage(),
- appView),
+ method, i, instruction, ex.getMessage(), appView),
appView);
}
}
@@ -1038,40 +1015,33 @@
}
private Int2ReferenceSortedMap<FrameType> computeInitialLocals(
- DexType context, DexEncodedMethod method, RewrittenPrototypeDescription protoTypeChanges) {
+ AppView<?> appView,
+ DexMethod method,
+ boolean isInstance,
+ RewrittenPrototypeDescription prototypeChanges) {
+ DexItemFactory dexItemFactory = appView.dexItemFactory();
Int2ReferenceSortedMap<FrameType> initialLocals = new Int2ReferenceAVLTreeMap<>();
int index = 0;
- if (method.isInstanceInitializer()) {
- initialLocals.put(index++, FrameType.uninitializedThis());
- } else if (!method.getAccessFlags().isStatic()) {
- initialLocals.put(index++, FrameType.initialized(context));
+ if (isInstance) {
+ initialLocals.put(
+ index++,
+ method.isInstanceInitializer(dexItemFactory)
+ || method.mustBeInlinedIntoInstanceInitializer(appView)
+ || method.isHorizontallyMergedInstanceInitializer(dexItemFactory)
+ ? FrameType.uninitializedThis()
+ : FrameType.initialized(method.getHolderType()));
}
- ArgumentInfoCollection argumentsInfo = protoTypeChanges.getArgumentInfoCollection();
- DexType[] parameters = method.getReference().proto.parameters.values;
- int originalNumberOfArguments =
- parameters.length
- + argumentsInfo.numberOfRemovedArguments()
- + initialLocals.size()
- - protoTypeChanges.numberOfExtraParameters();
- int argumentIndex = index;
- int usedArgumentIndex = 0;
- while (argumentIndex < originalNumberOfArguments) {
- ArgumentInfo argumentInfo = argumentsInfo.getArgumentInfo(argumentIndex++);
- DexType localType;
- if (argumentInfo.isRemovedArgumentInfo()) {
- localType = argumentInfo.asRemovedArgumentInfo().getType();
- } else {
- if (argumentInfo.isRewrittenTypeInfo()) {
- assert parameters[usedArgumentIndex] == argumentInfo.asRewrittenTypeInfo().getNewType();
- localType = argumentInfo.asRewrittenTypeInfo().getOldType();
- } else {
- localType = parameters[usedArgumentIndex];
- }
- usedArgumentIndex++;
- }
- FrameType frameType = FrameType.initialized(localType);
+ for (DexType parameter : method.getParameters()) {
+ FrameType frameType = FrameType.initialized(parameter);
initialLocals.put(index++, frameType);
- if (localType.isWideType()) {
+ if (frameType.isWide()) {
+ initialLocals.put(index++, frameType);
+ }
+ }
+ for (ExtraParameter extraParameter : prototypeChanges.getExtraParameters()) {
+ FrameType frameType = FrameType.initialized(extraParameter.getType(dexItemFactory));
+ initialLocals.put(index++, frameType);
+ if (frameType.isWide()) {
initialLocals.put(index++, frameType);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java b/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
index b6d1b1e..1a25ce6 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.cf.code.CfInstruction;
-import com.android.tools.r8.origin.Origin;
public class CfCodeStackMapValidatingException extends RuntimeException {
@@ -18,36 +17,43 @@
}
public static CfCodeDiagnostics unexpectedStackMapFrame(
- Origin origin, DexMethod method, AppView<?> appView) {
+ ProgramMethod method, AppView<?> appView) {
StringBuilder sb = new StringBuilder("Unexpected stack map frame without target");
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(origin, method, sb.toString());
+ return new CfCodeDiagnostics(
+ method.getOrigin(),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ sb.toString());
}
- public static CfCodeDiagnostics multipleFramesForLabel(
- Origin origin, DexMethod method, AppView<?> appView) {
+ public static CfCodeDiagnostics multipleFramesForLabel(ProgramMethod method, AppView<?> appView) {
StringBuilder sb = new StringBuilder("Multiple frames for label");
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(origin, method, sb.toString());
+ return new CfCodeDiagnostics(
+ method.getOrigin(),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ sb.toString());
}
public static CfCodeDiagnostics noFramesForMethodWithJumps(
- Origin origin, DexMethod method, AppView<?> appView) {
+ ProgramMethod method, AppView<?> appView) {
StringBuilder sb =
new StringBuilder("Expected stack map table for method with non-linear control flow.");
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(origin, method, sb.toString());
+ return new CfCodeDiagnostics(
+ method.getOrigin(),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ sb.toString());
}
public static CfCodeDiagnostics toDiagnostics(
- Origin origin,
- DexMethod method,
+ ProgramMethod method,
int instructionIndex,
CfInstruction instruction,
String detailMessage,
@@ -63,6 +69,9 @@
if (appView.enableWholeProgramOptimizations()) {
sb.append(" In later version of R8, the method may be assumed not reachable.");
}
- return new CfCodeDiagnostics(origin, method, sb.toString());
+ return new CfCodeDiagnostics(
+ method.getOrigin(),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ sb.toString());
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index a260816..0f4233d 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -88,7 +88,11 @@
return false;
}
- public boolean isHorizontalClassMergingCode() {
+ public boolean isHorizontalClassMergerCode() {
+ return false;
+ }
+
+ public boolean isIncompleteHorizontalClassMergerCode() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexApplication.java b/src/main/java/com/android/tools/r8/graph/DexApplication.java
index feedd6c..5dd4a97 100644
--- a/src/main/java/com/android/tools/r8/graph/DexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DexApplication.java
@@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.function.Consumer;
import java.util.function.Predicate;
public abstract class DexApplication implements DexDefinitionSupplier {
@@ -116,6 +117,10 @@
abstract Collection<DexProgramClass> programClasses();
+ public abstract void forEachProgramType(Consumer<DexType> consumer);
+
+ public abstract void forEachLibraryType(Consumer<DexType> consumer);
+
public Collection<DexProgramClass> classes() {
ReorderBox<DexProgramClass> box = new ReorderBox<>(programClasses());
assert box.reorderClasses();
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
index 0beeb2f..09f740e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -148,8 +148,7 @@
// No indexed items to collect.
}
- @Override
- public int estimatedWriteSize() {
+ public static int estimatedWriteSize(int parameterCount, int maxPc) {
return LebUtils.sizeAsUleb128(START_LINE)
+ LebUtils.sizeAsUleb128(parameterCount)
+ parameterCount * LebUtils.sizeAsUleb128(0)
@@ -159,6 +158,11 @@
}
@Override
+ public int estimatedWriteSize() {
+ return estimatedWriteSize(parameterCount, maxPc);
+ }
+
+ @Override
public void write(
DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
writer.putUleb128(START_LINE);
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 3640575..08488c1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -320,6 +320,8 @@
createString(Constants.CLASS_INITIALIZER_NAME);
public final DexString temporaryConstructorMethodPrefix =
createString(Constants.TEMPORARY_INSTANCE_INITIALIZER_PREFIX);
+ public final DexString syntheticConstructorMethodPrefix =
+ createString(Constants.SYNTHETIC_INSTANCE_INITIALIZER_PREFIX);
public final DexString thisName = createString("this");
public final DexString lambdaInstanceFieldName = createString(LAMBDA_INSTANCE_FIELD_NAME);
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index 0cd5a14..466e1cf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -296,8 +296,21 @@
return factory.isConstructor(this);
}
- public boolean mustBeInlinedIntoInstanceInitializer(DexItemFactory dexItemFactory) {
- return getName().startsWith(dexItemFactory.temporaryConstructorMethodPrefix);
+ public boolean mustBeInlinedIntoInstanceInitializer(AppView<?> appView) {
+ DexItemFactory dexItemFactory = appView.dexItemFactory();
+ if (getName().startsWith(dexItemFactory.temporaryConstructorMethodPrefix)) {
+ DexClassAndMethod method = appView.definitionFor(this);
+ return method != null
+ && appView
+ .graphLens()
+ .getOriginalMethodSignature(this)
+ .isInstanceInitializer(dexItemFactory);
+ }
+ return false;
+ }
+
+ public boolean isHorizontallyMergedInstanceInitializer(DexItemFactory dexItemFactory) {
+ return getName().startsWith(dexItemFactory.syntheticConstructorMethodPrefix);
}
public DexMethod withExtraArgumentPrepended(DexType type, DexItemFactory dexItemFactory) {
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index dd95a2d..1f756ee 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -23,6 +23,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
public class DirectMappedDexApplication extends DexApplication {
@@ -65,6 +66,16 @@
return programClasses;
}
+ @Override
+ public void forEachProgramType(Consumer<DexType> consumer) {
+ programClasses.forEach(clazz -> consumer.accept(clazz.type));
+ }
+
+ @Override
+ public void forEachLibraryType(Consumer<DexType> consumer) {
+ libraryClasses.forEach((type, clazz) -> consumer.accept(type));
+ }
+
public Collection<DexLibraryClass> libraryClasses() {
return libraryClasses.values();
}
diff --git a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
index b781f0b..49ef4af 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
@@ -54,6 +54,16 @@
}
@Override
+ public void forEachProgramType(Consumer<DexType> consumer) {
+ programClasses.getAllTypes().forEach(consumer);
+ }
+
+ @Override
+ public void forEachLibraryType(Consumer<DexType> consumer) {
+ libraryClasses.getAllClassProviderTypes().forEach(consumer);
+ }
+
+ @Override
public ClassResolutionResult contextIndependentDefinitionForWithResolutionResult(DexType type) {
ClassResolutionResult.Builder builder = ClassResolutionResult.builder();
if (libraryClasses != null) {
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 37acbad..3cb1a4c 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -42,7 +42,7 @@
GraphLens codeLens = appView.graphLens();
RewrittenPrototypeDescription protoChanges = RewrittenPrototypeDescription.none();
if (methodProcessor.shouldApplyCodeRewritings(this)) {
- codeLens = appView.codeLens();
+ codeLens = getDefinition().getCode().getCodeLens(appView);
protoChanges = appView.graphLens().lookupPrototypeChangesForMethodDefinition(getReference());
}
return code.buildInliningIR(
diff --git a/src/main/java/com/android/tools/r8/graph/proto/ArgumentInfoCollection.java b/src/main/java/com/android/tools/r8/graph/proto/ArgumentInfoCollection.java
index cbfa83d..889f21a 100644
--- a/src/main/java/com/android/tools/r8/graph/proto/ArgumentInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/proto/ArgumentInfoCollection.java
@@ -34,26 +34,31 @@
private final Int2ObjectSortedMap<ArgumentInfo> argumentInfos;
private final int argumentInfosSize;
private final ArgumentPermutation argumentPermutation;
+ private final boolean isConvertedToStaticMethod;
// Specific constructor for empty.
private ArgumentInfoCollection() {
this.argumentInfos = EMPTY_MAP;
this.argumentInfosSize = -1;
this.argumentPermutation = ArgumentPermutation.getDefault();
+ this.isConvertedToStaticMethod = false;
}
private ArgumentInfoCollection(
Int2ObjectSortedMap<ArgumentInfo> argumentInfos,
int argumentInfosSize,
- ArgumentPermutation argumentPermutation) {
+ ArgumentPermutation argumentPermutation,
+ boolean isConvertedToStaticMethod) {
assert argumentInfos != null;
assert argumentPermutation != null;
assert !argumentInfos.isEmpty() || argumentInfos == EMPTY_MAP;
- assert !argumentInfos.isEmpty() || !argumentPermutation.isDefault() : "should use empty.";
+ assert !argumentInfos.isEmpty() || !argumentPermutation.isDefault() || isConvertedToStaticMethod
+ : "should use empty.";
assert argumentInfosSize >= 0;
this.argumentInfos = argumentInfos;
this.argumentInfosSize = argumentInfosSize;
this.argumentPermutation = argumentPermutation;
+ this.isConvertedToStaticMethod = isConvertedToStaticMethod;
}
public static ArgumentInfoCollection empty() {
@@ -161,6 +166,10 @@
return argumentPermutation.getNewArgumentIndex(intermediateArgumentIndex);
}
+ public boolean isConvertedToStaticMethod() {
+ return isConvertedToStaticMethod;
+ }
+
public int size() {
assert !isEmpty();
return argumentInfosSize;
@@ -187,7 +196,10 @@
builder.addArgumentInfo(argumentIndex, argumentInfo);
}
});
- return builder.setArgumentInfosSize(argumentInfosSize).build();
+ return builder
+ .setArgumentInfosSize(argumentInfosSize)
+ .setIsConvertedToStaticMethod(isConvertedToStaticMethod())
+ .build();
}
return this;
}
@@ -203,12 +215,14 @@
ArgumentInfoCollection other = (ArgumentInfoCollection) obj;
return argumentInfos.equals(other.argumentInfos)
&& argumentPermutation.equals(other.argumentPermutation)
- && argumentInfosSize == other.argumentInfosSize;
+ && argumentInfosSize == other.argumentInfosSize
+ && isConvertedToStaticMethod == other.isConvertedToStaticMethod;
}
@Override
public int hashCode() {
- return Objects.hash(argumentInfos, argumentPermutation, argumentInfosSize);
+ return Objects.hash(
+ argumentInfos, argumentPermutation, argumentInfosSize, isConvertedToStaticMethod);
}
public static Builder builder() {
@@ -220,6 +234,7 @@
private Int2ObjectSortedMap<ArgumentInfo> argumentInfos = new Int2ObjectRBTreeMap<>();
private int argumentInfosSize = -1;
private ArgumentPermutation argumentPermutation = ArgumentPermutation.getDefault();
+ private boolean isConvertedToStaticMethod;
public Builder addArgumentInfo(int argumentIndex, ArgumentInfo argInfo) {
argumentInfos.put(argumentIndex, argInfo);
@@ -240,7 +255,9 @@
}
public boolean isEmpty() {
- return argumentInfos.isEmpty() && argumentPermutation.isDefault();
+ return argumentInfos.isEmpty()
+ && argumentPermutation.isDefault()
+ && !isConvertedToStaticMethod;
}
public Builder setArgumentInfosSize(int argumentInfosSize) {
@@ -253,6 +270,15 @@
return this;
}
+ public Builder setIsConvertedToStaticMethod() {
+ return setIsConvertedToStaticMethod(true);
+ }
+
+ public Builder setIsConvertedToStaticMethod(boolean isConvertedToStaticMethod) {
+ this.isConvertedToStaticMethod = isConvertedToStaticMethod;
+ return this;
+ }
+
public ArgumentInfoCollection build() {
if (isEmpty()) {
return empty();
@@ -260,7 +286,7 @@
Int2ObjectSortedMap<ArgumentInfo> argumentInfosOrEmpty =
argumentInfos.isEmpty() ? EMPTY_MAP : argumentInfos;
return new ArgumentInfoCollection(
- argumentInfosOrEmpty, argumentInfosSize, argumentPermutation);
+ argumentInfosOrEmpty, argumentInfosSize, argumentPermutation, isConvertedToStaticMethod);
}
}
@@ -315,9 +341,14 @@
argumentPermutationBuilder.setNewArgumentIndex(argumentIndex, newArgumentIndex);
}
}
+ assert BooleanUtils.intValue(isConvertedToStaticMethod())
+ + BooleanUtils.intValue(other.isConvertedToStaticMethod())
+ <= 1;
return builder
.setArgumentInfosSize(argumentInfosSize)
.setArgumentPermutation(argumentPermutationBuilder.build())
+ .setIsConvertedToStaticMethod(
+ isConvertedToStaticMethod() || other.isConvertedToStaticMethod())
.build();
}
diff --git a/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java b/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java
index 8459d85..06c5418 100644
--- a/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java
+++ b/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java
@@ -20,7 +20,6 @@
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.conversion.ExtraParameter;
-import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfoFixer;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableList;
@@ -252,18 +251,12 @@
extraParameters, newRewrittenReturnInfo, argumentInfoCollection);
}
- public RewrittenPrototypeDescription withExtraUnusedNullParameters(
- int numberOfExtraUnusedNullParameters) {
- List<ExtraParameter> parameters =
- Collections.nCopies(numberOfExtraUnusedNullParameters, new ExtraUnusedNullParameter());
- return withExtraParameters(parameters);
- }
-
public RewrittenPrototypeDescription withExtraParameters(ExtraParameter... parameters) {
return withExtraParameters(Arrays.asList(parameters));
}
- public RewrittenPrototypeDescription withExtraParameters(List<ExtraParameter> parameters) {
+ public RewrittenPrototypeDescription withExtraParameters(
+ List<? extends ExtraParameter> parameters) {
if (parameters.isEmpty()) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index 78a8743..303efef 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -143,7 +143,8 @@
if (!definition.getCode().isCfCode()) {
assert appView.options().isGeneratingDex();
assert mode.isFinal();
- syntheticInitializerConverterBuilder.add(new ProgramMethod(group.getTarget(), definition));
+ syntheticInitializerConverterBuilder.addClassInitializer(
+ new ProgramMethod(group.getTarget(), definition));
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index dd7de45..4b79710 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -121,10 +121,7 @@
SyntheticInitializerConverter syntheticInitializerConverter =
syntheticInitializerConverterBuilder.build();
- if (!syntheticInitializerConverter.isEmpty()) {
- assert mode.isFinal();
- syntheticInitializerConverterBuilder.build().convert(executorService);
- }
+ syntheticInitializerConverter.convertClassInitializers(executorService);
// Generate the graph lens.
HorizontallyMergedClasses mergedClasses =
@@ -144,15 +141,18 @@
// sites, fields accesses, etc. are correctly transferred to the target classes.
appView.rewriteWithLensAndApplication(
horizontalClassMergerGraphLens, getNewApplication(mergedClasses));
+ codeProvider.setGraphLens(horizontalClassMergerGraphLens);
// Record where the synthesized $r8$classId fields are read and written.
if (mode.isInitial()) {
createFieldAccessInfoCollectionModifier(groups).modify(appView.withLiveness());
- transformIncompleteCode(groups, horizontalClassMergerGraphLens, executorService);
} else {
assert groups.stream().noneMatch(MergeGroup::hasClassIdField);
}
+ transformIncompleteCode(groups, horizontalClassMergerGraphLens, executorService);
+ syntheticInitializerConverter.convertInstanceInitializers(executorService);
+
appView.pruneItems(
prunedItems.toBuilder().setPrunedApp(appView.app()).build(), executorService);
@@ -197,11 +197,11 @@
if (group.hasClassIdField()) {
DexProgramClass target = group.getTarget();
target.forEachProgramInstanceInitializerMatching(
- definition -> definition.getCode().isHorizontalClassMergingCode(),
+ definition -> definition.getCode().isHorizontalClassMergerCode(),
method -> builder.recordFieldWrittenInContext(group.getClassIdField(), method));
target.forEachProgramVirtualMethodMatching(
definition ->
- definition.hasCode() && definition.getCode().isHorizontalClassMergingCode(),
+ definition.hasCode() && definition.getCode().isHorizontalClassMergerCode(),
method -> builder.recordFieldReadInContext(group.getClassIdField(), method));
}
}
@@ -216,20 +216,19 @@
ThreadUtils.processItems(
groups,
group -> {
- if (group.hasClassIdField()) {
- DexProgramClass target = group.getTarget();
- target.forEachProgramVirtualMethodMatching(
- definition ->
- definition.hasCode()
- && definition.getCode() instanceof IncompleteVirtuallyMergedMethodCode,
- method -> {
- IncompleteVirtuallyMergedMethodCode code =
- (IncompleteVirtuallyMergedMethodCode) method.getDefinition().getCode();
- method
- .getDefinition()
- .setCode(code.toCfCode(method, horizontalClassMergerGraphLens), appView);
- });
- }
+ DexProgramClass target = group.getTarget();
+ target.forEachProgramMethodMatching(
+ definition ->
+ definition.hasCode()
+ && definition.getCode().isIncompleteHorizontalClassMergerCode(),
+ method -> {
+ IncompleteHorizontalClassMergerCode code =
+ (IncompleteHorizontalClassMergerCode) method.getDefinition().getCode();
+ method
+ .getDefinition()
+ .setCode(
+ code.toCfCode(appView, method, horizontalClassMergerGraphLens), appView);
+ });
},
executorService);
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerCfCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerCfCode.java
deleted file mode 100644
index ce6f6be..0000000
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerCfCode.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2021, 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.horizontalclassmerging;
-
-import com.android.tools.r8.cf.code.CfInstruction;
-import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.DexType;
-import java.util.List;
-
-/**
- * Similar to CfCode, but with a marker that makes it possible to recognize this is synthesized by
- * the horizontal class merger.
- */
-public class HorizontalClassMergerCfCode extends CfCode {
-
- HorizontalClassMergerCfCode(
- DexType originalHolder, int maxStack, int maxLocals, List<CfInstruction> instructions) {
- super(originalHolder, maxStack, maxLocals, instructions);
- }
-
- @Override
- public boolean isHorizontalClassMergingCode() {
- return true;
- }
-}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
index 75743d6..14465fd 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -272,7 +272,8 @@
}
}
- void addExtraParameters(DexMethod methodSignature, List<ExtraParameter> extraParameters) {
+ void addExtraParameters(
+ DexMethod methodSignature, List<? extends ExtraParameter> extraParameters) {
Set<DexMethod> originalMethodSignatures = methodMap.getKeys(methodSignature);
if (originalMethodSignatures.isEmpty()) {
methodExtraParameters
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IRCodeProvider.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IRCodeProvider.java
index 6976e5a..9f74d8e 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/IRCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IRCodeProvider.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.IRCode;
@@ -23,6 +24,7 @@
AppView<AppInfo> appViewForConversion =
AppView.createForD8(AppInfo.createInitialAppInfo(appView.appInfo().app()));
appViewForConversion.setGraphLens(appView.graphLens());
+ appViewForConversion.setCodeLens(appView.codeLens());
this.appViewForConversion = appViewForConversion;
}
@@ -32,4 +34,8 @@
.getCode()
.buildIR(method, appViewForConversion, method.getOrigin());
}
+
+ public void setGraphLens(GraphLens graphLens) {
+ appViewForConversion.setGraphLens(graphLens);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java
new file mode 100644
index 0000000..d961949
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteHorizontalClassMergerCode.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2022, 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.horizontalclassmerging;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.ClasspathMethod;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.origin.Origin;
+
+public abstract class IncompleteHorizontalClassMergerCode extends Code {
+
+ @Override
+ public boolean isHorizontalClassMergerCode() {
+ return true;
+ }
+
+ @Override
+ public boolean isIncompleteHorizontalClassMergerCode() {
+ return true;
+ }
+
+ public abstract CfCode toCfCode(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ ProgramMethod method,
+ HorizontalClassMergerGraphLens lens);
+
+ // Implement Code.
+
+ @Override
+ public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
+ throw new Unreachable();
+ }
+
+ @Override
+ protected boolean computeEquals(Object other) {
+ throw new Unreachable();
+ }
+
+ @Override
+ protected int computeHashCode() {
+ throw new Unreachable();
+ }
+
+ @Override
+ public int estimatedDexCodeSizeUpperBoundInBytes() {
+ throw new Unreachable();
+ }
+
+ @Override
+ public boolean isEmptyVoidMethod() {
+ throw new Unreachable();
+ }
+
+ @Override
+ public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public abstract String toString();
+
+ @Override
+ public String toString(DexEncodedMethod method, ClassNameMapper naming) {
+ return toString();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
new file mode 100644
index 0000000..f60f332
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
@@ -0,0 +1,245 @@
+// Copyright (c) 2022, 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.horizontalclassmerging;
+
+import com.android.tools.r8.cf.code.CfConstClass;
+import com.android.tools.r8.cf.code.CfConstNull;
+import com.android.tools.r8.cf.code.CfConstNumber;
+import com.android.tools.r8.cf.code.CfConstString;
+import com.android.tools.r8.cf.code.CfDexItemBasedConstString;
+import com.android.tools.r8.cf.code.CfInstanceFieldWrite;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfLoad;
+import com.android.tools.r8.cf.code.CfPosition;
+import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.value.SingleConstValue;
+import com.android.tools.r8.ir.analysis.value.SingleDexItemBasedStringValue;
+import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.Position.SyntheticPosition;
+import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.ir.conversion.ExtraParameter;
+import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfo;
+import com.android.tools.r8.utils.IntBox;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.Map;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Similar to CfCode, but with a marker that makes it possible to recognize this is synthesized by
+ * the horizontal class merger.
+ */
+public class IncompleteMergedInstanceInitializerCode extends IncompleteHorizontalClassMergerCode {
+
+ private final DexField classIdField;
+ private final int extraNulls;
+ private final DexMethod originalMethodReference;
+ private final DexMethod syntheticMethodReference;
+
+ private final Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPre;
+ private final Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPost;
+
+ private final DexMethod parentConstructor;
+ private final List<InstanceFieldInitializationInfo> parentConstructorArguments;
+
+ IncompleteMergedInstanceInitializerCode(
+ DexField classIdField,
+ int extraNulls,
+ DexMethod originalMethodReference,
+ DexMethod syntheticMethodReference,
+ Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPre,
+ Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignmentsPost,
+ DexMethod parentConstructor,
+ List<InstanceFieldInitializationInfo> parentConstructorArguments) {
+ this.classIdField = classIdField;
+ this.extraNulls = extraNulls;
+ this.originalMethodReference = originalMethodReference;
+ this.syntheticMethodReference = syntheticMethodReference;
+ this.instanceFieldAssignmentsPre = instanceFieldAssignmentsPre;
+ this.instanceFieldAssignmentsPost = instanceFieldAssignmentsPost;
+ this.parentConstructor = parentConstructor;
+ this.parentConstructorArguments = parentConstructorArguments;
+ }
+
+ @Override
+ public CfCode toCfCode(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ ProgramMethod method,
+ HorizontalClassMergerGraphLens lens) {
+ int[] argumentToLocalIndex = new int[method.getDefinition().getNumberOfArguments()];
+ int maxLocals = 0;
+ for (int argumentIndex = 0; argumentIndex < argumentToLocalIndex.length; argumentIndex++) {
+ argumentToLocalIndex[argumentIndex] = maxLocals;
+ maxLocals += method.getArgumentType(argumentIndex).getRequiredRegisters();
+ }
+
+ IntBox maxStack = new IntBox();
+ ImmutableList.Builder<CfInstruction> instructionBuilder = ImmutableList.builder();
+
+ // Set position.
+ Position callerPosition =
+ SyntheticPosition.builder().setLine(0).setMethod(syntheticMethodReference).build();
+ Position calleePosition =
+ SyntheticPosition.builder()
+ .setLine(0)
+ .setMethod(originalMethodReference)
+ .setCallerPosition(callerPosition)
+ .build();
+ CfPosition position = new CfPosition(new CfLabel(), calleePosition);
+ instructionBuilder.add(position);
+ instructionBuilder.add(position.getLabel());
+
+ // Assign class id.
+ if (classIdField != null) {
+ int classIdLocalIndex = maxLocals - 1 - extraNulls;
+ instructionBuilder.add(new CfLoad(ValueType.OBJECT, 0));
+ instructionBuilder.add(new CfLoad(ValueType.INT, classIdLocalIndex));
+ instructionBuilder.add(
+ new CfInstanceFieldWrite(
+ lens.getRenamedFieldSignature(classIdField, lens.getPrevious())));
+ maxStack.set(2);
+ }
+
+ // Assign each field.
+ addCfInstructionsForInstanceFieldAssignments(
+ instructionBuilder, instanceFieldAssignmentsPre, argumentToLocalIndex, maxStack, lens);
+
+ // Load receiver for parent constructor call.
+ int stackHeightForParentConstructorCall = 1;
+ instructionBuilder.add(new CfLoad(ValueType.OBJECT, 0));
+
+ // Load constructor arguments.
+ MethodLookupResult parentConstructorLookup = lens.lookupInvokeDirect(parentConstructor, method);
+
+ int i = 0;
+ for (InstanceFieldInitializationInfo initializationInfo : parentConstructorArguments) {
+ stackHeightForParentConstructorCall +=
+ addCfInstructionsForInitializationInfo(
+ instructionBuilder,
+ initializationInfo,
+ argumentToLocalIndex,
+ parentConstructorLookup.getReference().getParameter(i));
+ i++;
+ }
+
+ for (ExtraParameter extraParameter :
+ parentConstructorLookup.getPrototypeChanges().getExtraParameters()) {
+ stackHeightForParentConstructorCall +=
+ addCfInstructionsForInitializationInfo(
+ instructionBuilder,
+ extraParameter.getValue(appView),
+ argumentToLocalIndex,
+ parentConstructorLookup.getReference().getParameter(i));
+ i++;
+ }
+
+ assert i == parentConstructorLookup.getReference().getParameters().size();
+
+ // Invoke parent constructor.
+ instructionBuilder.add(
+ new CfInvoke(Opcodes.INVOKESPECIAL, parentConstructorLookup.getReference(), false));
+ maxStack.setMax(stackHeightForParentConstructorCall);
+
+ // Assign each field.
+ addCfInstructionsForInstanceFieldAssignments(
+ instructionBuilder, instanceFieldAssignmentsPost, argumentToLocalIndex, maxStack, lens);
+
+ // Return.
+ instructionBuilder.add(new CfReturnVoid());
+
+ return new CfCode(
+ originalMethodReference.getHolderType(),
+ maxStack.get(),
+ maxLocals,
+ instructionBuilder.build()) {
+
+ @Override
+ public GraphLens getCodeLens(AppView<?> appView) {
+ return lens;
+ }
+ };
+ }
+
+ private static void addCfInstructionsForInstanceFieldAssignments(
+ ImmutableList.Builder<CfInstruction> instructionBuilder,
+ Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignments,
+ int[] argumentToLocalIndex,
+ IntBox maxStack,
+ HorizontalClassMergerGraphLens lens) {
+ instanceFieldAssignments.forEach(
+ (field, initializationInfo) -> {
+ // Load the receiver, the field value, and then set the field.
+ instructionBuilder.add(new CfLoad(ValueType.OBJECT, 0));
+ int stackSizeForInitializationInfo =
+ addCfInstructionsForInitializationInfo(
+ instructionBuilder, initializationInfo, argumentToLocalIndex, field.getType());
+ instructionBuilder.add(
+ new CfInstanceFieldWrite(lens.getRenamedFieldSignature(field, lens.getPrevious())));
+ maxStack.setMax(stackSizeForInitializationInfo + 1);
+ });
+ }
+
+ private static int addCfInstructionsForInitializationInfo(
+ ImmutableList.Builder<CfInstruction> instructionBuilder,
+ InstanceFieldInitializationInfo initializationInfo,
+ int[] argumentToLocalIndex,
+ DexType type) {
+ if (initializationInfo.isArgumentInitializationInfo()) {
+ int argumentIndex = initializationInfo.asArgumentInitializationInfo().getArgumentIndex();
+ instructionBuilder.add(
+ new CfLoad(ValueType.fromDexType(type), argumentToLocalIndex[argumentIndex]));
+ return type.getRequiredRegisters();
+ }
+
+ assert initializationInfo.isSingleValue();
+ assert initializationInfo.asSingleValue().isSingleConstValue();
+
+ SingleConstValue singleConstValue = initializationInfo.asSingleValue().asSingleConstValue();
+ if (singleConstValue.isSingleConstClassValue()) {
+ instructionBuilder.add(
+ new CfConstClass(singleConstValue.asSingleConstClassValue().getType()));
+ return 1;
+ } else if (singleConstValue.isSingleDexItemBasedStringValue()) {
+ SingleDexItemBasedStringValue dexItemBasedStringValue =
+ singleConstValue.asSingleDexItemBasedStringValue();
+ instructionBuilder.add(
+ new CfDexItemBasedConstString(
+ dexItemBasedStringValue.getItem(), dexItemBasedStringValue.getNameComputationInfo()));
+ return 1;
+ } else if (singleConstValue.isSingleNumberValue()) {
+ if (type.isReferenceType()) {
+ assert singleConstValue.isNull();
+ instructionBuilder.add(new CfConstNull());
+ return 1;
+ } else {
+ instructionBuilder.add(
+ new CfConstNumber(
+ singleConstValue.asSingleNumberValue().getValue(), ValueType.fromDexType(type)));
+ return type.getRequiredRegisters();
+ }
+ } else {
+ assert singleConstValue.isSingleStringValue();
+ instructionBuilder.add(
+ new CfConstString(singleConstValue.asSingleStringValue().getDexString()));
+ return 1;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "IncompleteMergedInstanceInitializerCode";
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java
index 65aed84..835daa4 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java
@@ -15,22 +15,15 @@
import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.cf.code.CfSwitch;
import com.android.tools.r8.cf.code.CfSwitch.Kind;
-import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.ClasspathMethod;
-import com.android.tools.r8.graph.Code;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.naming.ClassNameMapper;
-import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.IterableUtils;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
@@ -44,9 +37,10 @@
/**
* A short-lived piece of code that will be converted into {@link CfCode} using the method {@link
- * #toCfCode(ProgramMethod, HorizontalClassMergerGraphLens)}.
+ * IncompleteHorizontalClassMergerCode#toCfCode(AppView, ProgramMethod,
+ * HorizontalClassMergerGraphLens)}.
*/
-public class IncompleteVirtuallyMergedMethodCode extends Code {
+public class IncompleteVirtuallyMergedMethodCode extends IncompleteHorizontalClassMergerCode {
private final DexField classIdField;
private final Int2ReferenceSortedMap<DexMethod> mappedMethods;
@@ -64,11 +58,6 @@
this.originalMethod = originalMethod;
}
- @Override
- public boolean isHorizontalClassMergingCode() {
- return true;
- }
-
/**
* Given a mapping from class ids to methods to invoke, this creates a piece of {@link CfCode} on
* the following form.
@@ -91,7 +80,11 @@
* methods may be changed as a result of the horizontal class merger's fixup (e.g., if the method
* signature refers to a horizontally merged type).
*/
- public CfCode toCfCode(ProgramMethod method, HorizontalClassMergerGraphLens lens) {
+ @Override
+ public CfCode toCfCode(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ ProgramMethod method,
+ HorizontalClassMergerGraphLens lens) {
// We store each argument in a local.
int maxLocals = 1 + IterableUtils.sumInt(method.getParameters(), DexType::getRequiredRegisters);
@@ -157,13 +150,7 @@
@Override
public GraphLens getCodeLens(AppView<?> appView) {
- GraphLens graphLens =
- appView
- .graphLens()
- .asNonIdentityLens()
- .find(GraphLens::isHorizontalClassMergerGraphLens);
- assert graphLens != null;
- return graphLens;
+ return lens;
}
};
}
@@ -195,50 +182,8 @@
return locals;
}
- // Implement Code.
-
- @Override
- public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
- throw new Unreachable();
- }
-
- @Override
- protected boolean computeEquals(Object other) {
- throw new Unreachable();
- }
-
- @Override
- protected int computeHashCode() {
- throw new Unreachable();
- }
-
- @Override
- public int estimatedDexCodeSizeUpperBoundInBytes() {
- throw new Unreachable();
- }
-
- @Override
- public boolean isEmptyVoidMethod() {
- throw new Unreachable();
- }
-
- @Override
- public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
- throw new Unreachable();
- }
-
- @Override
- public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
- throw new Unreachable();
- }
-
@Override
public String toString() {
return "IncompleteVirtuallyMergedMethodCode";
}
-
- @Override
- public String toString(DexEncodedMethod method, ClassNameMapper naming) {
- return toString();
- }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java
index 7aa753c..894c017 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerDescription.java
@@ -4,40 +4,18 @@
package com.android.tools.r8.horizontalclassmerging;
-import com.android.tools.r8.cf.code.CfConstClass;
-import com.android.tools.r8.cf.code.CfConstNull;
-import com.android.tools.r8.cf.code.CfConstNumber;
-import com.android.tools.r8.cf.code.CfConstString;
-import com.android.tools.r8.cf.code.CfDexItemBasedConstString;
-import com.android.tools.r8.cf.code.CfInstanceFieldWrite;
-import com.android.tools.r8.cf.code.CfInstruction;
-import com.android.tools.r8.cf.code.CfInvoke;
-import com.android.tools.r8.cf.code.CfLabel;
-import com.android.tools.r8.cf.code.CfLoad;
-import com.android.tools.r8.cf.code.CfPosition;
-import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.analysis.value.SingleConstValue;
-import com.android.tools.r8.ir.analysis.value.SingleDexItemBasedStringValue;
-import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.code.Position.SyntheticPosition;
-import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfo;
-import com.android.tools.r8.utils.IntBox;
-import com.google.common.collect.ImmutableList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import org.objectweb.asm.Opcodes;
/**
* A simple abstraction of an instance initializer's code, which allows a parent constructor call
@@ -91,146 +69,21 @@
* @param syntheticMethodReference the original, synthetic reference of the new method reference
* ($r8$init$synthetic)
*/
- public CfCode createCfCode(
- DexMethod newMethodReference,
+ public IncompleteMergedInstanceInitializerCode createCfCode(
DexMethod originalMethodReference,
DexMethod syntheticMethodReference,
MergeGroup group,
boolean hasClassId,
int extraNulls) {
- int[] argumentToLocalIndex =
- new int[newMethodReference.getParameters().size() + 1 - extraNulls];
- int maxLocals = 0;
- argumentToLocalIndex[0] = maxLocals++;
- for (int i = 1; i < argumentToLocalIndex.length; i++) {
- argumentToLocalIndex[i] = maxLocals;
- maxLocals += newMethodReference.getParameter(i - 1).getRequiredRegisters();
- }
-
- IntBox maxStack = new IntBox();
- ImmutableList.Builder<CfInstruction> instructionBuilder = ImmutableList.builder();
-
- // Set position.
- Position callerPosition =
- SyntheticPosition.builder().setLine(0).setMethod(syntheticMethodReference).build();
- Position calleePosition =
- SyntheticPosition.builder()
- .setLine(0)
- .setMethod(originalMethodReference)
- .setCallerPosition(callerPosition)
- .build();
- CfPosition position = new CfPosition(new CfLabel(), calleePosition);
- instructionBuilder.add(position);
- instructionBuilder.add(position.getLabel());
-
- // Assign class id.
- if (group.hasClassIdField()) {
- assert hasClassId;
- int classIdLocalIndex = maxLocals - 1;
- instructionBuilder.add(new CfLoad(ValueType.OBJECT, 0));
- instructionBuilder.add(new CfLoad(ValueType.INT, classIdLocalIndex));
- instructionBuilder.add(new CfInstanceFieldWrite(group.getClassIdField()));
- maxStack.set(2);
- } else {
- assert !hasClassId;
- }
-
- // Assign each field.
- addCfInstructionsForInstanceFieldAssignments(
- instructionBuilder, instanceFieldAssignmentsPre, argumentToLocalIndex, maxStack);
-
- // Load receiver for parent constructor call.
- int stackHeightForParentConstructorCall = 1;
- instructionBuilder.add(new CfLoad(ValueType.OBJECT, 0));
-
- // Load constructor arguments.
- int i = 0;
- for (InstanceFieldInitializationInfo initializationInfo : parentConstructorArguments) {
- stackHeightForParentConstructorCall +=
- addCfInstructionsForInitializationInfo(
- instructionBuilder,
- initializationInfo,
- argumentToLocalIndex,
- parentConstructor.getParameter(i));
- i++;
- }
-
- // Invoke parent constructor.
- instructionBuilder.add(new CfInvoke(Opcodes.INVOKESPECIAL, parentConstructor, false));
- maxStack.setMax(stackHeightForParentConstructorCall);
-
- // Assign each field.
- addCfInstructionsForInstanceFieldAssignments(
- instructionBuilder, instanceFieldAssignmentsPost, argumentToLocalIndex, maxStack);
-
- // Return.
- instructionBuilder.add(new CfReturnVoid());
-
- return new HorizontalClassMergerCfCode(
- newMethodReference.getHolderType(), maxStack.get(), maxLocals, instructionBuilder.build());
- }
-
- private static void addCfInstructionsForInstanceFieldAssignments(
- ImmutableList.Builder<CfInstruction> instructionBuilder,
- Map<DexField, InstanceFieldInitializationInfo> instanceFieldAssignments,
- int[] argumentToLocalIndex,
- IntBox maxStack) {
- instanceFieldAssignments.forEach(
- (field, initializationInfo) -> {
- // Load the receiver, the field value, and then set the field.
- instructionBuilder.add(new CfLoad(ValueType.OBJECT, 0));
- int stackSizeForInitializationInfo =
- addCfInstructionsForInitializationInfo(
- instructionBuilder, initializationInfo, argumentToLocalIndex, field.getType());
- instructionBuilder.add(new CfInstanceFieldWrite(field));
- maxStack.setMax(stackSizeForInitializationInfo + 1);
- });
- }
-
- private static int addCfInstructionsForInitializationInfo(
- ImmutableList.Builder<CfInstruction> instructionBuilder,
- InstanceFieldInitializationInfo initializationInfo,
- int[] argumentToLocalIndex,
- DexType type) {
- if (initializationInfo.isArgumentInitializationInfo()) {
- int argumentIndex = initializationInfo.asArgumentInitializationInfo().getArgumentIndex();
- instructionBuilder.add(
- new CfLoad(ValueType.fromDexType(type), argumentToLocalIndex[argumentIndex]));
- return type.getRequiredRegisters();
- }
-
- assert initializationInfo.isSingleValue();
- assert initializationInfo.asSingleValue().isSingleConstValue();
-
- SingleConstValue singleConstValue = initializationInfo.asSingleValue().asSingleConstValue();
- if (singleConstValue.isSingleConstClassValue()) {
- instructionBuilder.add(
- new CfConstClass(singleConstValue.asSingleConstClassValue().getType()));
- return 1;
- } else if (singleConstValue.isSingleDexItemBasedStringValue()) {
- SingleDexItemBasedStringValue dexItemBasedStringValue =
- singleConstValue.asSingleDexItemBasedStringValue();
- instructionBuilder.add(
- new CfDexItemBasedConstString(
- dexItemBasedStringValue.getItem(), dexItemBasedStringValue.getNameComputationInfo()));
- return 1;
- } else if (singleConstValue.isSingleNumberValue()) {
- if (type.isReferenceType()) {
- assert singleConstValue.isNull();
- instructionBuilder.add(new CfConstNull());
- return 1;
- } else {
- instructionBuilder.add(
- new CfConstNumber(
- singleConstValue.asSingleNumberValue().getValue(), ValueType.fromDexType(type)));
- return type.getRequiredRegisters();
- }
- } else {
- assert singleConstValue.isSingleStringValue();
- instructionBuilder.add(
- new CfConstString(singleConstValue.asSingleStringValue().getDexString()));
- return 1;
- }
+ return new IncompleteMergedInstanceInitializerCode(
+ hasClassId ? group.getClassIdField() : null,
+ extraNulls,
+ originalMethodReference,
+ syntheticMethodReference,
+ instanceFieldAssignmentsPre,
+ instanceFieldAssignmentsPost,
+ parentConstructor,
+ parentConstructorArguments);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java
index 3c97009..1c3443b 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/InstanceInitializerMerger.java
@@ -34,7 +34,6 @@
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
public class InstanceInitializerMerger {
@@ -143,11 +142,11 @@
* synthesized constructor all-though it by construction doesn't have any unused arguments.
*/
private DexMethod getSyntheticMethodReference(
- ClassMethodsBuilder classMethodsBuilder, ProgramMethod representative) {
+ ClassMethodsBuilder classMethodsBuilder, DexMethod newMethodReference) {
return dexItemFactory.createFreshMethodNameWithoutHolder(
- "$r8$init$synthetic",
- representative.getProto(),
- representative.getHolderType(),
+ Constants.SYNTHETIC_INSTANCE_INITIALIZER_PREFIX,
+ newMethodReference.getProto(),
+ newMethodReference.getHolderType(),
classMethodsBuilder::isFresh);
}
@@ -276,7 +275,6 @@
int extraNulls) {
if (hasInstanceInitializerDescription()) {
return instanceInitializerDescription.createCfCode(
- newMethodReference,
getOriginalMethodReference(),
syntheticMethodReference,
group,
@@ -318,7 +316,11 @@
newMethodReferenceTemplate,
mode.isInitial() ? syntheticArgumentClass.getArgumentClasses() : ImmutableList.of(),
classMethodsBuilder::isFresh);
- int extraNulls = newMethodReference.getArity() - newMethodReferenceTemplate.getArity();
+
+ // Compute the extra unused null parameters.
+ List<ExtraUnusedNullParameter> extraUnusedNullParameters =
+ ExtraUnusedNullParameter.computeExtraUnusedNullParameters(
+ newMethodReferenceTemplate, newMethodReference);
// Verify that the merge is a simple renaming in the final round of merging.
assert mode.isInitial() || newMethodReference == newMethodReferenceTemplate;
@@ -340,7 +342,7 @@
// Add a mapping from a synthetic name to the synthetic constructor.
DexMethod syntheticMethodReference =
- getSyntheticMethodReference(classMethodsBuilder, representative);
+ getSyntheticMethodReference(classMethodsBuilder, newMethodReference);
if (!isSingleton() || group.hasClassIdField()) {
lensBuilder.recordNewMethodSignature(syntheticMethodReference, newMethodReference, true);
}
@@ -352,7 +354,7 @@
int classIdentifier = classIdentifiers.getInt(instanceInitializer.getHolderType());
extraParameters.add(new ExtraConstantIntParameter(classIdentifier));
}
- extraParameters.addAll(Collections.nCopies(extraNulls, new ExtraUnusedNullParameter()));
+ extraParameters.addAll(extraUnusedNullParameters);
lensBuilder.mapMergedConstructor(
instanceInitializer.getReference(), newMethodReference, extraParameters);
}
@@ -363,7 +365,11 @@
.setMethod(newMethodReference)
.setAccessFlags(getNewAccessFlags())
.setCode(
- getNewCode(newMethodReference, syntheticMethodReference, needsClassId, extraNulls))
+ getNewCode(
+ newMethodReference,
+ syntheticMethodReference,
+ needsClassId,
+ extraUnusedNullParameters.size()))
.setClassFileVersion(getNewClassFileVersion())
.setApiLevelForDefinition(representativeMethod.getApiLevelForDefinition())
.setApiLevelForCode(representativeMethod.getApiLevelForCode())
@@ -372,11 +378,12 @@
if (mode.isFinal()) {
if (appView.options().isGeneratingDex() && !newInstanceInitializer.getCode().isDexCode()) {
- syntheticInitializerConverterBuilder.add(
+ syntheticInitializerConverterBuilder.addInstanceInitializer(
new ProgramMethod(group.getTarget(), newInstanceInitializer));
} else {
assert appView.options().isGeneratingDex()
- || newInstanceInitializer.getCode().isCfWritableCode();
+ || newInstanceInitializer.getCode().isCfWritableCode()
+ || newInstanceInitializer.getCode().isIncompleteHorizontalClassMergerCode();
}
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
index 0c36573..183664a 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
@@ -30,7 +30,6 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.Collection;
-import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -293,10 +292,10 @@
newMethodReference,
syntheticArgumentClass.getArgumentClasses(),
tryMethod -> !newMethods.contains(tryMethod.getSignature()));
- int extraNulls = newMethodReference.getArity() - originalMethodReference.getArity();
lensBuilder.addExtraParameters(
originalMethodReference,
- Collections.nCopies(extraNulls, new ExtraUnusedNullParameter()));
+ ExtraUnusedNullParameter.computeExtraUnusedNullParameters(
+ originalMethodReference, newMethodReference));
} else {
newMethodReference =
dexItemFactory.createFreshMethodNameWithoutHolder(
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java
index 3a9f744..60903cc 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ConstructorEntryPointSynthesizedCode.java
@@ -53,7 +53,7 @@
}
@Override
- public boolean isHorizontalClassMergingCode() {
+ public boolean isHorizontalClassMergerCode() {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java
index d2414ed..446d245 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java
@@ -27,15 +27,18 @@
private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final IRCodeProvider codeProvider;
- private final List<ProgramMethod> methods;
+ private final List<ProgramMethod> classInitializers;
+ private final List<ProgramMethod> instanceInitializers;
private SyntheticInitializerConverter(
AppView<? extends AppInfoWithClassHierarchy> appView,
IRCodeProvider codeProvider,
- List<ProgramMethod> methods) {
+ List<ProgramMethod> classInitializers,
+ List<ProgramMethod> instanceInitializers) {
this.appView = appView;
this.codeProvider = codeProvider;
- this.methods = methods;
+ this.classInitializers = classInitializers;
+ this.instanceInitializers = instanceInitializers;
}
public static Builder builder(
@@ -43,7 +46,24 @@
return new Builder(appView, codeProvider);
}
- public void convert(ExecutorService executorService) throws ExecutionException {
+ public void convertClassInitializers(ExecutorService executorService) throws ExecutionException {
+ if (!classInitializers.isEmpty()) {
+ IRConverter converter = new IRConverter(createAppViewForConversion(), Timing.empty());
+ ThreadUtils.processItems(
+ classInitializers, method -> processMethod(method, converter), executorService);
+ }
+ }
+
+ public void convertInstanceInitializers(ExecutorService executorService)
+ throws ExecutionException {
+ if (!instanceInitializers.isEmpty()) {
+ IRConverter converter = new IRConverter(createAppViewForConversion(), Timing.empty());
+ ThreadUtils.processItems(
+ instanceInitializers, method -> processMethod(method, converter), executorService);
+ }
+ }
+
+ private AppView<AppInfo> createAppViewForConversion() {
// At this point the code rewritings described by repackaging and synthetic finalization have
// not been applied to the code objects. These code rewritings will be applied in the
// application writer. We therefore simulate that we are in D8, to allow building IR for each of
@@ -52,28 +72,26 @@
AppView<AppInfo> appViewForConversion =
AppView.createForD8(AppInfo.createInitialAppInfo(appView.appInfo().app()));
appViewForConversion.setGraphLens(appView.graphLens());
+ appViewForConversion.setCodeLens(appView.codeLens());
+ return appViewForConversion;
+ }
- // Build IR for each of the class initializers and finalize.
- IRConverter converter = new IRConverter(appViewForConversion, Timing.empty());
- ThreadUtils.processItems(
- methods,
- method -> {
- IRCode code = codeProvider.buildIR(method);
- converter.removeDeadCodeAndFinalizeIR(
- code, OptimizationFeedbackIgnore.getInstance(), Timing.empty());
- },
- executorService);
+ private void processMethod(ProgramMethod method, IRConverter converter) {
+ IRCode code = codeProvider.buildIR(method);
+ converter.removeDeadCodeAndFinalizeIR(
+ code, OptimizationFeedbackIgnore.getInstance(), Timing.empty());
}
public boolean isEmpty() {
- return methods.isEmpty();
+ return classInitializers.isEmpty() && instanceInitializers.isEmpty();
}
public static class Builder {
private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final IRCodeProvider codeProvider;
- private final List<ProgramMethod> methods = new ArrayList<>();
+ private final List<ProgramMethod> classInitializers = new ArrayList<>();
+ private final List<ProgramMethod> instanceInitializers = new ArrayList<>();
private Builder(
AppView<? extends AppInfoWithClassHierarchy> appView, IRCodeProvider codeProvider) {
@@ -81,13 +99,19 @@
this.codeProvider = codeProvider;
}
- public Builder add(ProgramMethod method) {
- this.methods.add(method);
+ public Builder addClassInitializer(ProgramMethod method) {
+ this.classInitializers.add(method);
+ return this;
+ }
+
+ public Builder addInstanceInitializer(ProgramMethod method) {
+ this.instanceInitializers.add(method);
return this;
}
public SyntheticInitializerConverter build() {
- return new SyntheticInitializerConverter(appView, codeProvider, methods);
+ return new SyntheticInitializerConverter(
+ appView, codeProvider, classInitializers, instanceInitializers);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index e78ade7..edd3468 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -37,7 +37,15 @@
}
public int getIndex() {
- assert verifyIndex();
+ return getIndex(true);
+ }
+
+ public int getIndexRaw() {
+ return getIndex(false);
+ }
+
+ private int getIndex(boolean verifyIndex) {
+ assert !verifyIndex || verifyIndex();
return index;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
index 358369b..60d87b7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
@@ -310,7 +310,7 @@
DexItemFactory dexItemFactory = appView.dexItemFactory();
DexMethod invokedMethod = toBeReplaced.asInvokeDirect().getInvokedMethod();
if (invokedMethod.isInstanceInitializer(dexItemFactory)
- || invokedMethod.mustBeInlinedIntoInstanceInitializer(dexItemFactory)) {
+ || invokedMethod.mustBeInlinedIntoInstanceInitializer(appView)) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java
index d7abfac..02c2319 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Phi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java
@@ -211,7 +211,7 @@
current.removePhiUser(this);
}
- void replaceOperand(Value current, Value newValue) {
+ public void replaceOperand(Value current, Value newValue) {
for (int i = 0; i < operands.size(); i++) {
if (operands.get(i) == current) {
operands.set(i, newValue);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 4f4a7b2..e95d612 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -26,9 +26,9 @@
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadata;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadataProvider;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -81,7 +81,7 @@
private static final int IINC_PATTERN_SIZE = 4;
public final AppView<?> appView;
- private final DexEncodedMethod method;
+ private final ProgramMethod method;
private final IRCode code;
private Map<BasicBlock, CfLabel> labels;
@@ -135,7 +135,7 @@
public CfBuilder(
AppView<?> appView,
- DexEncodedMethod method,
+ ProgramMethod method,
IRCode code,
BytecodeMetadataProvider bytecodeMetadataProvider) {
this.appView = appView;
@@ -193,12 +193,12 @@
DexBuilder.removeRedundantDebugPositions(code);
CfCode code = buildCfCode();
assert verifyInvokeInterface(code, appView);
- assert code.verifyFrames(method, appView, this.code.origin).isValid();
+ assert code.verifyFrames(method, appView, appView.graphLens()).isValid();
return code;
}
private Set<UninitializedThisLocalRead> insertUninitializedThisLocalReads() {
- if (!method.isInstanceInitializer()) {
+ if (!method.getDefinition().isInstanceInitializer()) {
return Collections.emptySet();
}
// Find all non-normal exit blocks.
@@ -249,7 +249,7 @@
for (Instruction insn : block.getInstructions()) {
if (insn.isNewInstance()) {
initializers.put(insn.asNewInstance(), computeInitializers(insn.outValue()));
- } else if (insn.isArgument() && method.isInstanceInitializer()) {
+ } else if (insn.isArgument() && method.getDefinition().isInstanceInitializer()) {
if (insn.outValue().isThis()) {
// By JVM8 §4.10.1.9 (invokespecial), a this() or super() call in a constructor
// changes the type of `this` from uninitializedThis
@@ -259,7 +259,7 @@
}
}
}
- assert !(method.isInstanceInitializer() && thisInitializers == null);
+ assert !(method.getDefinition().isInstanceInitializer() && thisInitializers == null);
}
private List<InvokeDirect> computeInitializers(Value value) {
@@ -383,8 +383,8 @@
}
com.android.tools.r8.position.Position diagnosticPosition =
com.android.tools.r8.position.Position.UNKNOWN;
- if (method.getCode().isCfCode()) {
- diagnosticPosition = method.getCode().asCfCode().getDiagnosticPosition();
+ if (method.getDefinition().getCode().isCfCode()) {
+ diagnosticPosition = method.getDefinition().getCode().asCfCode().getDiagnosticPosition();
}
return new CfCode(
method.getHolderType(),
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/ExtraUnusedNullParameter.java b/src/main/java/com/android/tools/r8/ir/conversion/ExtraUnusedNullParameter.java
index 0532a48..cc8a8c7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/ExtraUnusedNullParameter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/ExtraUnusedNullParameter.java
@@ -6,24 +6,40 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.SingleNumberValue;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
public class ExtraUnusedNullParameter extends ExtraParameter {
private final DexType type;
- @Deprecated
- public ExtraUnusedNullParameter() {
- this(null);
- }
-
public ExtraUnusedNullParameter(DexType type) {
this.type = type;
}
+ public static List<ExtraUnusedNullParameter> computeExtraUnusedNullParameters(
+ DexMethod from, DexMethod to) {
+ int numberOfExtraNullParameters = to.getArity() - from.getArity();
+ if (numberOfExtraNullParameters == 0) {
+ return Collections.emptyList();
+ }
+ List<ExtraUnusedNullParameter> extraUnusedNullParameters =
+ new ArrayList<>(numberOfExtraNullParameters);
+ for (int extraUnusedNullParameterIndex = from.getArity();
+ extraUnusedNullParameterIndex < to.getParameters().size();
+ extraUnusedNullParameterIndex++) {
+ DexType extraUnusedNullParameterType = to.getParameter(extraUnusedNullParameterIndex);
+ extraUnusedNullParameters.add(new ExtraUnusedNullParameter(extraUnusedNullParameterType));
+ }
+ return extraUnusedNullParameters;
+ }
+
@Override
public DexType getType(DexItemFactory dexItemFactory) {
assert type != null;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 664da13..0ac2896 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -74,6 +74,7 @@
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.MemberValuePropagation;
+import com.android.tools.r8.ir.optimize.NaturalIntLoopRemover;
import com.android.tools.r8.ir.optimize.PeepholeOptimizer;
import com.android.tools.r8.ir.optimize.RedundantFieldLoadAndStoreElimination;
import com.android.tools.r8.ir.optimize.ReflectionOptimizer;
@@ -142,6 +143,7 @@
private final InternalOptions options;
private final CfgPrinter printer;
public final CodeRewriter codeRewriter;
+ private final NaturalIntLoopRemover naturalIntLoopRemover = new NaturalIntLoopRemover();
private final ConstantCanonicalizer constantCanonicalizer;
public final MemberValuePropagation memberValuePropagation;
private final LensCodeRewriter lensCodeRewriter;
@@ -1300,6 +1302,9 @@
timing.begin("Rewrite array length");
codeRewriter.rewriteKnownArrayLengthCalls(code);
timing.end();
+ timing.begin("Natural Int Loop Remover");
+ naturalIntLoopRemover.run(code);
+ timing.end();
timing.begin("Rewrite AssertionError");
codeRewriter.rewriteAssertionErrorTwoArgumentConstructor(code, options);
timing.end();
@@ -1638,11 +1643,11 @@
OptimizationFeedback feedback,
MethodConversionOptions conversionOptions,
BytecodeMetadataProvider bytecodeMetadataProvider) {
- DexEncodedMethod method = code.method();
- assert !method.getCode().isDexCode();
+ ProgramMethod method = code.context();
+ assert !method.getDefinition().getCode().isDexCode();
CfBuilder builder = new CfBuilder(appView, method, code, bytecodeMetadataProvider);
CfCode result = builder.build(deadCodeRemover, conversionOptions);
- method.setCode(result, appView);
+ method.getDefinition().setCode(result, appView);
markProcessed(code, feedback);
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 613ab36..309cf22 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -885,7 +885,8 @@
ListIterator<Instruction> argumentPostludeIterator = argumentPostlude.listIterator();
while (argumentPostludeIterator.hasNext()) {
Instruction current = argumentPostludeIterator.next();
- if (!current.isArgument() || replacement.getIndex() < current.asArgument().getIndex()) {
+ if (!current.isArgument()
+ || replacement.getIndexRaw() < current.asArgument().getIndexRaw()) {
argumentPostludeIterator.previous();
break;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
index bd146e9..c943028 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
@@ -4,11 +4,14 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.utils.Reporter;
import java.util.Map;
/**
@@ -18,21 +21,34 @@
*/
public class DesugaredLibraryAmender {
- private final AppView<?> appView;
+ private final DexDefinitionSupplier definitions;
+ private final Reporter reporter;
+ private final ComputedApiLevel minAPILevel;
public static void run(AppView<?> appView) {
- run(appView, appView.options().machineDesugaredLibrarySpecification.getAmendLibraryMethods());
+ run(
+ appView.options().machineDesugaredLibrarySpecification.getAmendLibraryMethods(),
+ appView,
+ appView.options().reporter,
+ appView.computedMinApiLevel());
}
- public static void run(AppView<?> appView, Map<DexMethod, MethodAccessFlags> amendLibrary) {
+ public static void run(
+ Map<DexMethod, MethodAccessFlags> amendLibrary,
+ DexDefinitionSupplier definitions,
+ Reporter reporter,
+ ComputedApiLevel minAPILevel) {
if (amendLibrary.isEmpty()) {
return;
}
- new DesugaredLibraryAmender(appView).run(amendLibrary);
+ new DesugaredLibraryAmender(definitions, reporter, minAPILevel).run(amendLibrary);
}
- private DesugaredLibraryAmender(AppView<?> appView) {
- this.appView = appView;
+ private DesugaredLibraryAmender(
+ DexDefinitionSupplier definitions, Reporter reporter, ComputedApiLevel minAPILevel) {
+ this.definitions = definitions;
+ this.reporter = reporter;
+ this.minAPILevel = minAPILevel;
}
private void run(Map<DexMethod, MethodAccessFlags> amendLibrary) {
@@ -40,17 +56,14 @@
}
private void amendLibraryMethod(DexMethod method, MethodAccessFlags methodAccessFlags) {
- DexClass dexClass = appView.contextIndependentDefinitionFor(method.getHolderType());
+ DexClass dexClass = definitions.contextIndependentDefinitionFor(method.getHolderType());
if (dexClass == null || !dexClass.isLibraryClass()) {
// Consider just throwing an error.
- appView
- .options()
- .reporter
- .warning(
- "Desugared library: Cannot amend library method "
- + method
- + " because the holder is not a library class"
- + (dexClass == null ? "(null)." : "."));
+ reporter.warning(
+ "Desugared library: Cannot amend library method "
+ + method
+ + " because the holder is not a library class"
+ + (dexClass == null ? "(null)." : "."));
return;
}
if (dexClass.lookupMethod(method) != null) {
@@ -61,7 +74,7 @@
.setMethod(method)
.setAccessFlags(methodAccessFlags)
.setCode(null)
- .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForDefinition(minAPILevel)
.build();
dexClass.getMethodCollection().addMethod(encodedMethod);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecification.java
index f96e5cd..9d3bf12 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecification.java
@@ -4,12 +4,11 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
@@ -24,14 +23,6 @@
return false;
}
- default LegacyDesugaredLibrarySpecification asLegacyDesugaredLibrarySpecification() {
- return null;
- }
-
- default HumanDesugaredLibrarySpecification asHumanDesugaredLibrarySpecification() {
- return null;
- }
-
boolean isEmpty();
boolean isLibraryCompilation();
@@ -45,14 +36,15 @@
AndroidApiLevel getRequiredCompilationApiLevel();
MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, AndroidApp app) throws IOException;
+ InternalOptions options, AndroidApp app, Timing timing) throws IOException;
MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, Path library, Path desugaredJDKLib) throws IOException;
+ InternalOptions options, Path library, Timing timing, Path desugaredJDKLib)
+ throws IOException;
default MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, Path library) throws IOException {
+ InternalOptions options, Path library, Timing timing) throws IOException {
assert !isLibraryCompilation();
- return toMachineSpecification(options, library, null);
+ return toMachineSpecification(options, library, timing, null);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
index 157dcc6..238ae7b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
@@ -3,22 +3,16 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
public class HumanDesugaredLibrarySpecification implements DesugaredLibrarySpecification {
@@ -35,6 +29,11 @@
this.rewritingFlags = rewritingFlags;
}
+ public static HumanDesugaredLibrarySpecification empty() {
+ return new HumanDesugaredLibrarySpecification(
+ HumanTopLevelFlags.empty(), HumanRewritingFlags.empty(), false);
+ }
+
@Override
public boolean isEmpty() {
return rewritingFlags.isEmpty();
@@ -45,11 +44,6 @@
return true;
}
- @Override
- public HumanDesugaredLibrarySpecification asHumanDesugaredLibrarySpecification() {
- return this;
- }
-
public boolean supportAllCallbacksFromLibrary() {
return topLevelFlags.supportAllCallbacksFromLibrary();
}
@@ -81,61 +75,6 @@
return topLevelFlags.getIdentifier();
}
- public Map<String, String> getRewritePrefix() {
- return rewritingFlags.getRewritePrefix();
- }
-
- public boolean hasEmulatedLibraryInterfaces() {
- return !getEmulateLibraryInterface().isEmpty();
- }
-
- public Map<DexType, DexType> getEmulateLibraryInterface() {
- return rewritingFlags.getEmulatedInterfaces();
- }
-
- // If the method is retargeted, answers the retargeted method, else null.
- public DexMethod retargetMethod(DexEncodedMethod method, AppView<?> appView) {
- Map<DexMethod, DexType> retargetCoreLibMember = rewritingFlags.getRetargetMethod();
- DexType dexType = retargetCoreLibMember.get(method.getReference());
- if (dexType != null) {
- return appView
- .dexItemFactory()
- .createMethod(
- dexType,
- appView.dexItemFactory().prependHolderToProto(method.getReference()),
- method.getName());
- }
- return null;
- }
-
- public DexMethod retargetMethod(DexClassAndMethod method, AppView<?> appView) {
- return retargetMethod(method.getDefinition(), appView);
- }
-
- public Map<DexMethod, DexType> getRetargetCoreLibMember() {
- return rewritingFlags.getRetargetMethod();
- }
-
- public Map<DexType, DexType> getBackportCoreLibraryMember() {
- return rewritingFlags.getLegacyBackport();
- }
-
- public Map<DexType, DexType> getCustomConversions() {
- return rewritingFlags.getCustomConversions();
- }
-
- public Set<DexType> getWrapperConversions() {
- return rewritingFlags.getWrapperConversions();
- }
-
- public Set<DexMethod> getDontRewriteInvocation() {
- return rewritingFlags.getDontRewriteInvocation();
- }
-
- public Set<DexType> getDontRetargetLibMember() {
- return rewritingFlags.getDontRetarget();
- }
-
@Override
public List<String> getExtraKeepRules() {
return topLevelFlags.getExtraKeepRules();
@@ -152,19 +91,15 @@
@Override
public MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, AndroidApp app) throws IOException {
- return new HumanToMachineSpecificationConverter()
- .convert(
- this,
- isLibraryCompilation() ? app.getProgramResourceProviders() : null,
- app.getLibraryResourceProviders(),
- options);
+ InternalOptions options, AndroidApp app, Timing timing) throws IOException {
+ return new HumanToMachineSpecificationConverter(timing).convert(this, app, options);
}
@Override
public MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, Path library, Path desugaredJDKLib) throws IOException {
- return new HumanToMachineSpecificationConverter()
- .convert(this, isLibraryCompilation() ? desugaredJDKLib : null, library, options);
+ InternalOptions options, Path library, Timing timing, Path desugaredJDKLib)
+ throws IOException {
+ return new HumanToMachineSpecificationConverter(timing)
+ .convertForTesting(this, desugaredJDKLib, library, options);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
index bb4bc68..e52cc02 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
@@ -176,9 +176,11 @@
if (formatVersion != CURRENT_HUMAN_CONFIGURATION_FORMAT_VERSION) {
reporter.warning(
new StringDiagnostic(
- "Human desugared library specification version mismatches the parser "
- + "expected version. This is allowed and should happen only while extending "
- + "the specifications.",
+ "Human desugared library specification format version "
+ + formatVersion
+ + " mismatches the parser expected version ("
+ + CURRENT_HUMAN_CONFIGURATION_FORMAT_VERSION
+ + "). This is allowed and should happen only while extending the specifications.",
origin));
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java
index 71227cf..3daf522 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
@@ -28,11 +28,6 @@
private final LegacyTopLevelFlags topLevelFlags;
private final LegacyRewritingFlags rewritingFlags;
- public static LegacyDesugaredLibrarySpecification empty() {
- return new LegacyDesugaredLibrarySpecification(
- LegacyTopLevelFlags.empty(), LegacyRewritingFlags.empty(), false);
- }
-
public LegacyDesugaredLibrarySpecification(
LegacyTopLevelFlags topLevelFlags,
LegacyRewritingFlags rewritingFlags,
@@ -52,11 +47,6 @@
return true;
}
- @Override
- public LegacyDesugaredLibrarySpecification asLegacyDesugaredLibrarySpecification() {
- return this;
- }
-
public LegacyTopLevelFlags getTopLevelFlags() {
return topLevelFlags;
}
@@ -88,18 +78,6 @@
return topLevelFlags.getIdentifier();
}
- public Map<String, String> getRewritePrefix() {
- return rewritingFlags.getRewritePrefix();
- }
-
- public boolean hasEmulatedLibraryInterfaces() {
- return !getEmulateLibraryInterface().isEmpty();
- }
-
- public Map<DexType, DexType> getEmulateLibraryInterface() {
- return rewritingFlags.getEmulateLibraryInterface();
- }
-
// If the method is retargeted, answers the retargeted method, else null.
public DexMethod retargetMethod(DexEncodedMethod method, AppView<?> appView) {
Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
@@ -120,14 +98,6 @@
return retargetMethod(method.getDefinition(), appView);
}
- public Map<DexString, Map<DexType, DexType>> getRetargetCoreLibMember() {
- return rewritingFlags.getRetargetCoreLibMember();
- }
-
- public Map<DexType, DexType> getBackportCoreLibraryMember() {
- return rewritingFlags.getBackportCoreLibraryMember();
- }
-
public Map<DexType, DexType> getCustomConversions() {
return rewritingFlags.getCustomConversions();
}
@@ -136,13 +106,6 @@
return rewritingFlags.getWrapperConversions();
}
- public List<Pair<DexType, DexString>> getDontRewriteInvocation() {
- return rewritingFlags.getDontRewriteInvocation();
- }
-
- public Set<DexType> getDontRetargetLibMember() {
- return rewritingFlags.getDontRetargetLibMember();
- }
@Override
public List<String> getExtraKeepRules() {
@@ -156,17 +119,18 @@
@Override
public MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, AndroidApp app) throws IOException {
- return new LegacyToHumanSpecificationConverter()
- .convert(this, app.getLibraryResourceProviders(), options)
- .toMachineSpecification(options, app);
+ InternalOptions options, AndroidApp app, Timing timing) throws IOException {
+ return new LegacyToHumanSpecificationConverter(timing)
+ .convert(this, app, options)
+ .toMachineSpecification(options, app, timing);
}
@Override
public MachineDesugaredLibrarySpecification toMachineSpecification(
- InternalOptions options, Path library, Path desugaredJDKLib) throws IOException {
- return new LegacyToHumanSpecificationConverter()
- .convert(this, library, options)
- .toMachineSpecification(options, library, desugaredJDKLib);
+ InternalOptions options, Path library, Timing timing, Path desugaredJDKLib)
+ throws IOException {
+ return new LegacyToHumanSpecificationConverter(timing)
+ .convertForTesting(this, desugaredJDKLib, library, options)
+ .toMachineSpecification(options, library, timing, desugaredJDKLib);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/AppForSpecConversion.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/AppForSpecConversion.java
new file mode 100644
index 0000000..45f9dae
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/AppForSpecConversion.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, 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.ir.desugar.desugaredlibrary.specificationconversion;
+
+import com.android.tools.r8.ClassFileResourceProvider;
+import com.android.tools.r8.ProgramResourceProvider;
+import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.Timing;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.concurrent.ExecutorService;
+
+public class AppForSpecConversion {
+ static DexApplication readApp(
+ AndroidApp inputApp, InternalOptions options, boolean libraryCompilation, Timing timing)
+ throws IOException {
+ timing.begin("Read App");
+ AndroidApp.Builder builder = AndroidApp.builder();
+ for (ClassFileResourceProvider classFileResourceProvider :
+ inputApp.getLibraryResourceProviders()) {
+ builder.addLibraryResourceProvider(classFileResourceProvider);
+ }
+ if (libraryCompilation) {
+ for (ProgramResourceProvider programResourceProvider :
+ inputApp.getProgramResourceProviders()) {
+ builder.addProgramResourceProvider(programResourceProvider);
+ }
+ }
+ DexApplication app = internalReadApp(builder.build(), options, timing);
+ timing.end();
+ return app;
+ }
+
+ static DexApplication readAppForTesting(
+ Path desugaredJDKLib,
+ Path androidLib,
+ InternalOptions options,
+ boolean libraryCompilation,
+ Timing timing)
+ throws IOException {
+ timing.begin("Read App for testing");
+ assert !libraryCompilation || desugaredJDKLib != null;
+ AndroidApp.Builder builder = AndroidApp.builder();
+ if (libraryCompilation) {
+ builder.addProgramFile(desugaredJDKLib);
+ }
+ AndroidApp inputApp = builder.addLibraryFile(androidLib).build();
+ DexApplication app = internalReadApp(inputApp, options, timing);
+ timing.end();
+ return app;
+ }
+
+ private static DexApplication internalReadApp(
+ AndroidApp inputApp, InternalOptions options, Timing timing) throws IOException {
+ timing.begin("Internal Read App");
+ ApplicationReader applicationReader = new ApplicationReader(inputApp, options, timing);
+ ExecutorService executorService = ThreadUtils.getExecutorService(options);
+ assert !options.ignoreJavaLibraryOverride;
+ options.ignoreJavaLibraryOverride = true;
+ DexApplication app = applicationReader.read(executorService);
+ options.ignoreJavaLibraryOverride = false;
+ timing.end();
+ return app;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
index 55ac78c..e0ae560 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
@@ -88,17 +87,13 @@
}
private void rewriteClasses() {
- for (DexClass clazz : appInfo.app().asDirect().libraryClasses()) {
- if (clazz.toString().contains("MonthDay")) {
- clazz.toString();
- }
- registerType(clazz.type);
- registerDifferentType(clazz.type);
- }
- for (DexClass clazz : appInfo.classes()) {
- registerType(clazz.type);
- registerDifferentType(clazz.type);
- }
+ appInfo.app().forEachLibraryType(this::registerClassType);
+ appInfo.app().forEachProgramType(this::registerClassType);
+ }
+
+ private void registerClassType(DexType type) {
+ registerType(type);
+ registerDifferentType(type);
}
private void registerType(DexType type) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
index 6268125..a5a27aa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
@@ -11,8 +11,6 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.MethodResolutionResult;
-import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
@@ -28,12 +26,10 @@
public class HumanToMachineRetargetConverter {
private final AppInfoWithClassHierarchy appInfo;
- private final SubtypingInfo subtypingInfo;
private final Set<DexMethod> missingMethods = Sets.newIdentityHashSet();
public HumanToMachineRetargetConverter(AppInfoWithClassHierarchy appInfo) {
this.appInfo = appInfo;
- subtypingInfo = SubtypingInfo.create(appInfo);
}
public void convertRetargetFlags(
@@ -91,31 +87,12 @@
DerivedMethod dispatchMethod =
new DerivedMethod(src.getReference(), SyntheticKind.RETARGET_CLASS);
LinkedHashMap<DexType, DerivedMethod> dispatchCases = new LinkedHashMap<>();
- assert validateNoOverride(src, appInfo, subtypingInfo);
builder.putEmulatedVirtualRetarget(
src.getReference(),
new EmulatedDispatchMethodDescriptor(
interfaceMethod, dispatchMethod, forwardingMethod, dispatchCases));
}
- private boolean validateNoOverride(
- DexEncodedMethod src, AppInfoWithClassHierarchy appInfo, SubtypingInfo subtypingInfo) {
- for (DexType subtype : subtypingInfo.subtypes(src.getHolderType())) {
- DexClass subclass = appInfo.definitionFor(subtype);
- MethodResolutionResult resolutionResult =
- appInfo.resolveMethodOn(subclass, src.getReference());
- // The resolution is not successful when compiling to dex if the method rewritten is missing
- // in Android.jar.
- assert !resolutionResult.isSuccessfulMemberResolutionResult()
- || resolutionResult.getResolvedMethod().getReference() == src.getReference()
- // There is a difference in the sql library between Android.jar and the JDK which leads
- // to this resolution when compiling Cf to Cf while the methods do not exist in Android.
- || (resolutionResult.getResolvedMethod().getHolderType().toString().contains("java.sql")
- && resolutionResult.getResolvedMethod().getName().toString().equals("toInstant"));
- }
- return true;
- }
-
private boolean isEmulatedInterfaceDispatch(
DexEncodedMethod method,
AppInfoWithClassHierarchy appInfo,
@@ -146,19 +123,10 @@
DexEncodedMethod foundMethod,
DexType type,
AppInfoWithClassHierarchy appInfo,
- SubtypingInfo subtypingInfo,
BiConsumer<DexMethod, DexMethod> consumer) {
DexMethod src = foundMethod.getReference();
DexMethod dest = src.withHolder(type, appInfo.dexItemFactory());
consumer.accept(src, dest);
- for (DexType subtype : subtypingInfo.subtypes(foundMethod.getHolderType())) {
- DexClass subclass = appInfo.definitionFor(subtype);
- MethodResolutionResult resolutionResult = appInfo.resolveMethodOn(subclass, src);
- if (resolutionResult.isSuccessfulMemberResolutionResult()
- && resolutionResult.getResolvedMethod().getReference() == src) {
- consumer.accept(src.withHolder(subtype, appInfo.dexItemFactory()), dest);
- }
- }
}
private void convertNonEmulatedVirtualRetarget(
@@ -167,7 +135,6 @@
foundMethod,
type,
appInfo,
- subtypingInfo,
(src, dest) ->
builder.putNonEmulatedVirtualRetarget(
src,
@@ -177,7 +144,6 @@
private void convertStaticRetarget(
MachineRewritingFlags.Builder builder, DexEncodedMethod foundMethod, DexType type) {
- convertNonEmulatedRetarget(
- foundMethod, type, appInfo, subtypingInfo, builder::putStaticRetarget);
+ convertNonEmulatedRetarget(foundMethod, type, appInfo, builder::putStaticRetarget);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
index 51516d4..c0bcd82 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
@@ -4,19 +4,15 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
-import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.ProgramResourceProvider;
-import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryAmender;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
@@ -27,7 +23,7 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineTopLevelFlags;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.Sets;
import java.io.IOException;
@@ -35,52 +31,43 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.ExecutorService;
public class HumanToMachineSpecificationConverter {
- private AppView<?> appView;
+ private AppInfoWithClassHierarchy appInfo;
+ private Reporter reporter;
private final Set<DexType> missingCustomConversions = Sets.newIdentityHashSet();
+ private final Timing timing;
- public MachineDesugaredLibrarySpecification convert(
- HumanDesugaredLibrarySpecification humanSpec,
- List<ProgramResourceProvider> desugaredJDKLib,
- List<ClassFileResourceProvider> library,
- InternalOptions options)
- throws IOException {
- assert !humanSpec.isLibraryCompilation() || desugaredJDKLib != null;
- AndroidApp.Builder builder = AndroidApp.builder();
- for (ClassFileResourceProvider classFileResourceProvider : library) {
- builder.addLibraryResourceProvider(classFileResourceProvider);
- }
- if (humanSpec.isLibraryCompilation()) {
- for (ProgramResourceProvider programResourceProvider : desugaredJDKLib) {
- builder.addProgramResourceProvider(programResourceProvider);
- }
- }
- return internalConvert(humanSpec, builder.build(), options);
+ public HumanToMachineSpecificationConverter(Timing timing) {
+ this.timing = timing;
}
public MachineDesugaredLibrarySpecification convert(
+ HumanDesugaredLibrarySpecification humanSpec, AndroidApp inputApp, InternalOptions options)
+ throws IOException {
+ DexApplication app =
+ AppForSpecConversion.readApp(inputApp, options, humanSpec.isLibraryCompilation(), timing);
+ return convert(humanSpec, app);
+ }
+
+ public MachineDesugaredLibrarySpecification convertForTesting(
HumanDesugaredLibrarySpecification humanSpec,
Path desugaredJDKLib,
Path androidLib,
InternalOptions options)
throws IOException {
- assert !humanSpec.isLibraryCompilation() || desugaredJDKLib != null;
- AndroidApp.Builder builder = AndroidApp.builder();
- if (humanSpec.isLibraryCompilation()) {
- builder.addProgramFile(desugaredJDKLib);
- }
- AndroidApp inputApp = builder.addLibraryFile(androidLib).build();
- return internalConvert(humanSpec, inputApp, options);
+ DexApplication app =
+ AppForSpecConversion.readAppForTesting(
+ desugaredJDKLib, androidLib, options, humanSpec.isLibraryCompilation(), timing);
+ return convert(humanSpec, app);
}
- private MachineDesugaredLibrarySpecification internalConvert(
- HumanDesugaredLibrarySpecification humanSpec, AndroidApp inputApp, InternalOptions options)
- throws IOException {
- DexApplication app = readApp(inputApp, options);
- appView = AppView.createForD8(AppInfo.createInitialAppInfo(app));
+ private MachineDesugaredLibrarySpecification convert(
+ HumanDesugaredLibrarySpecification humanSpec, DexApplication app) {
+ timing.begin("Human to machine convert");
+ reporter = app.options.reporter;
+ appInfo = AppInfoWithClassHierarchy.createForDesugaring(AppInfo.createInitialAppInfo(app));
LibraryValidator.validate(
app,
humanSpec.isLibraryCompilation(),
@@ -89,6 +76,7 @@
convertRewritingFlags(
humanSpec.getSynthesizedLibraryClassesPackagePrefix(), humanSpec.getRewritingFlags());
MachineTopLevelFlags topLevelFlags = convertTopLevelFlags(humanSpec.getTopLevelFlags());
+ timing.end();
return new MachineDesugaredLibrarySpecification(
humanSpec.isLibraryCompilation(), topLevelFlags, machineRewritingFlags);
}
@@ -105,9 +93,10 @@
private MachineRewritingFlags convertRewritingFlags(
String synthesizedPrefix, HumanRewritingFlags rewritingFlags) {
- AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+ timing.begin("convert rewriting flags");
MachineRewritingFlags.Builder builder = MachineRewritingFlags.builder();
- DesugaredLibraryAmender.run(appView, rewritingFlags.getAmendLibraryMethod());
+ DesugaredLibraryAmender.run(
+ rewritingFlags.getAmendLibraryMethod(), appInfo, reporter, ComputedApiLevel.unknown());
rewritingFlags.getAmendLibraryMethod().forEach(builder::amendLibraryMethod);
new HumanToMachineRetargetConverter(appInfo)
.convertRetargetFlags(rewritingFlags, builder, this::warnMissingReferences);
@@ -126,7 +115,9 @@
"Cannot register custom conversion due to missing type: ", missingCustomConversions);
rewritingFlags.getDontRetarget().forEach(builder::addDontRetarget);
rewritingFlags.getLegacyBackport().forEach(builder::putLegacyBackport);
- return builder.build();
+ MachineRewritingFlags machineFlags = builder.build();
+ timing.end();
+ return machineFlags;
}
private void convertCustomConversion(
@@ -152,16 +143,6 @@
builder.putCustomConversion(type, new CustomConversionDescriptor(toMethod, fromMethod));
}
- private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
- ApplicationReader applicationReader = new ApplicationReader(inputApp, options, Timing.empty());
- ExecutorService executorService = ThreadUtils.getExecutorService(options);
- assert !options.ignoreJavaLibraryOverride;
- options.ignoreJavaLibraryOverride = true;
- DirectMappedDexApplication app = applicationReader.read(executorService).toDirect();
- options.ignoreJavaLibraryOverride = false;
- return app;
- }
-
void warnMissingReferences(String message, Set<? extends DexReference> missingReferences) {
List<DexReference> memberList = new ArrayList<>(missingReferences);
memberList.sort(DexReference::compareTo);
@@ -178,6 +159,6 @@
if (memberList.isEmpty()) {
return;
}
- appView.options().reporter.warning("Specification conversion: " + message + memberList);
+ reporter.warning("Specification conversion: " + message + memberList);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
index 3a2c990..47ef9e3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
@@ -4,14 +4,13 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
-import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.StringResource;
-import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
@@ -34,8 +33,8 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Pair;
-import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -44,15 +43,22 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutorService;
public class LegacyToHumanSpecificationConverter {
- private static final String wrapperPrefix = "__wrapper__.";
- private AndroidApiLevel legacyHackLevel = AndroidApiLevel.N_MR1;
+ private static final String WRAPPER_PREFIX = "__wrapper__.";
+ private static final AndroidApiLevel LEGACY_HACK_LEVEL = AndroidApiLevel.N_MR1;
+ private final Timing timing;
+
+ public LegacyToHumanSpecificationConverter(Timing timing) {
+ this.timing = timing;
+ }
public void convertAllAPILevels(
- StringResource inputSpecification, Path androidLib, StringConsumer output)
+ StringResource inputSpecification,
+ Path desugaredJDKLib,
+ Path androidLib,
+ StringConsumer output)
throws IOException {
InternalOptions options = new InternalOptions();
MultiAPILevelLegacyDesugaredLibrarySpecification legacySpec =
@@ -60,18 +66,21 @@
options.dexItemFactory(), options.reporter)
.parseMultiLevelConfiguration(inputSpecification);
MultiAPILevelHumanDesugaredLibrarySpecification humanSpec =
- convertAllAPILevels(legacySpec, androidLib, options);
+ convertAllAPILevels(legacySpec, desugaredJDKLib, androidLib, options);
MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.export(humanSpec, output);
}
public MultiAPILevelHumanDesugaredLibrarySpecification convertAllAPILevels(
MultiAPILevelLegacyDesugaredLibrarySpecification legacySpec,
+ Path desugaredJDKLib,
Path androidLib,
InternalOptions options)
throws IOException {
+ timing.begin("Legacy to human all API convert");
Origin origin = legacySpec.getOrigin();
- AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
- DexApplication app = readApp(androidApp, options);
+ DexApplication app =
+ AppForSpecConversion.readAppForTesting(desugaredJDKLib, androidLib, options, true, timing);
+
HumanTopLevelFlags humanTopLevelFlags = convertTopLevelFlags(legacySpec.getTopLevelFlags());
Int2ObjectArrayMap<HumanRewritingFlags> commonFlags =
convertRewritingFlagMap(legacySpec.getCommonFlags(), app, origin);
@@ -87,32 +96,34 @@
origin, humanTopLevelFlags, commonFlags, libraryFlags, programFlags);
MultiAPILevelHumanDesugaredLibrarySpecificationFlagDeduplicator.deduplicateFlags(
humanSpec, options.reporter);
+ timing.end();
return humanSpec;
}
public HumanDesugaredLibrarySpecification convert(
+ LegacyDesugaredLibrarySpecification legacySpec, AndroidApp inputApp, InternalOptions options)
+ throws IOException {
+ DexApplication app =
+ AppForSpecConversion.readApp(inputApp, options, legacySpec.isLegacy(), timing);
+ return convert(legacySpec, app, options);
+ }
+
+ public HumanDesugaredLibrarySpecification convertForTesting(
LegacyDesugaredLibrarySpecification legacySpec,
- List<ClassFileResourceProvider> library,
+ Path desugaredJDKLib,
+ Path androidLib,
InternalOptions options)
throws IOException {
- AndroidApp.Builder builder = AndroidApp.builder();
- for (ClassFileResourceProvider classFileResourceProvider : library) {
- builder.addLibraryResourceProvider(classFileResourceProvider);
- }
- return internalConvert(legacySpec, builder.build(), options);
+ DexApplication app =
+ AppForSpecConversion.readAppForTesting(
+ desugaredJDKLib, androidLib, options, legacySpec.isLibraryCompilation(), timing);
+ return convert(legacySpec, app, options);
}
public HumanDesugaredLibrarySpecification convert(
- LegacyDesugaredLibrarySpecification legacySpec, Path androidLib, InternalOptions options)
+ LegacyDesugaredLibrarySpecification legacySpec, DexApplication app, InternalOptions options)
throws IOException {
- AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
- return internalConvert(legacySpec, androidApp, options);
- }
-
- public HumanDesugaredLibrarySpecification internalConvert(
- LegacyDesugaredLibrarySpecification legacySpec, AndroidApp inputApp, InternalOptions options)
- throws IOException {
- DexApplication app = readApp(inputApp, options);
+ timing.begin("Legacy to Human convert");
LibraryValidator.validate(
app,
legacySpec.isLibraryCompilation(),
@@ -125,22 +136,27 @@
Origin origin = Origin.unknown();
HumanRewritingFlags humanRewritingFlags =
convertRewritingFlags(legacySpec.getRewritingFlags(), app, origin);
- if (options.getMinApiLevel().isLessThanOrEqualTo(legacyHackLevel)
+ if (options.getMinApiLevel().isLessThanOrEqualTo(LEGACY_HACK_LEVEL)
&& legacySpec.isLibraryCompilation()) {
+ timing.begin("Legacy hacks");
HumanRewritingFlags.Builder builder =
humanRewritingFlags.newBuilder(app.options.reporter, origin);
legacyLibraryFlagHacks(app.dexItemFactory(), builder);
humanRewritingFlags = builder.build();
+ timing.end();
}
+
+ timing.end();
return new HumanDesugaredLibrarySpecification(
humanTopLevelFlags, humanRewritingFlags, legacySpec.isLibraryCompilation());
}
private void legacyLibraryFlagHacks(
Int2ObjectArrayMap<HumanRewritingFlags> libraryFlags, DexApplication app, Origin origin) {
- int level = legacyHackLevel.getLevel();
+ int level = LEGACY_HACK_LEVEL.getLevel();
HumanRewritingFlags humanRewritingFlags = libraryFlags.get(level);
if (humanRewritingFlags == null) {
+ // Skip CHM only configuration.
return;
}
HumanRewritingFlags.Builder builder =
@@ -180,12 +196,6 @@
builder.retargetMethod(source, target);
}
- private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
- ApplicationReader applicationReader = new ApplicationReader(inputApp, options, Timing.empty());
- ExecutorService executorService = ThreadUtils.getExecutorService(options);
- return applicationReader.read(executorService).toDirect();
- }
-
private Int2ObjectArrayMap<HumanRewritingFlags> convertRewritingFlagMap(
Int2ObjectMap<LegacyRewritingFlags> libFlags, DexApplication app, Origin origin) {
Int2ObjectArrayMap<HumanRewritingFlags> map = new Int2ObjectArrayMap<>();
@@ -195,8 +205,8 @@
private HumanRewritingFlags convertRewritingFlags(
LegacyRewritingFlags flags, DexApplication app, Origin origin) {
+ timing.begin("Convert rewriting flags");
HumanRewritingFlags.Builder builder = HumanRewritingFlags.builder(app.options.reporter, origin);
-
flags
.getRewritePrefix()
.forEach((prefix, rewritten) -> rewritePrefix(builder, prefix, rewritten));
@@ -205,15 +215,15 @@
flags.getCustomConversions().forEach(builder::putCustomConversion);
flags.getDontRetargetLibMember().forEach(builder::addDontRetargetLibMember);
flags.getWrapperConversions().forEach(builder::addWrapperConversion);
-
flags
.getRetargetCoreLibMember()
.forEach((name, typeMap) -> convertRetargetCoreLibMember(builder, app, name, typeMap));
flags
.getDontRewriteInvocation()
.forEach(pair -> convertDontRewriteInvocation(builder, app, pair));
-
- return builder.build();
+ HumanRewritingFlags humanFlags = builder.build();
+ timing.end();
+ return humanFlags;
}
private void rewritePrefix(HumanRewritingFlags.Builder builder, String prefix, String rewritten) {
@@ -224,14 +234,14 @@
builder.putRewriteDerivedPrefix(rewritten, prefix, rewritten);
return;
}
- if (prefix.equals(wrapperPrefix)) {
+ if (prefix.equals(WRAPPER_PREFIX)) {
// We hard code here this applies to java.nio and java.io only.
ImmutableMap<String, String> map =
ImmutableMap.of("java.nio.", "j$.nio.", "java.io.", "j$.io.");
map.forEach(
(k, v) -> {
- builder.putRewriteDerivedPrefix(k, wrapperPrefix + k, k);
- builder.putRewriteDerivedPrefix(k, wrapperPrefix + v, v);
+ builder.putRewriteDerivedPrefix(k, WRAPPER_PREFIX + k, k);
+ builder.putRewriteDerivedPrefix(k, WRAPPER_PREFIX + v, v);
});
return;
}
@@ -242,7 +252,8 @@
HumanRewritingFlags.Builder builder, DexApplication app, Pair<DexType, DexString> pair) {
DexClass dexClass = app.definitionFor(pair.getFirst());
assert dexClass != null;
- List<DexClassAndMethod> methodsWithName = findMethodsWithName(pair.getSecond(), dexClass);
+ List<DexClassAndMethod> methodsWithName =
+ findMethodsWithName(pair.getSecond(), dexClass, builder, app);
for (DexClassAndMethod dexClassAndMethod : methodsWithName) {
builder.addDontRewriteInvocation(dexClassAndMethod.getReference());
}
@@ -257,16 +268,37 @@
(type, rewrittenType) -> {
DexClass dexClass = app.definitionFor(type);
assert dexClass != null;
- List<DexClassAndMethod> methodsWithName = findMethodsWithName(name, dexClass);
+ List<DexClassAndMethod> methodsWithName =
+ findMethodsWithName(name, dexClass, builder, app);
for (DexClassAndMethod dexClassAndMethod : methodsWithName) {
builder.retargetMethod(dexClassAndMethod.getReference(), rewrittenType);
}
});
}
- private List<DexClassAndMethod> findMethodsWithName(DexString methodName, DexClass clazz) {
+ private List<DexClassAndMethod> findMethodsWithName(
+ DexString methodName,
+ DexClass clazz,
+ HumanRewritingFlags.Builder builder,
+ DexApplication app) {
List<DexClassAndMethod> found = new ArrayList<>();
clazz.forEachClassMethodMatching(definition -> definition.getName() == methodName, found::add);
+ if (found.isEmpty()
+ && methodName.toString().equals("transferTo")
+ && clazz.type.toString().equals("java.io.InputStream")) {
+ // Special hack for JDK11 java.io.InputStream#transferTo which could not be specified
+ // correctly.
+ DexItemFactory factory = app.dexItemFactory();
+ DexProto proto =
+ factory.createProto(factory.longType, factory.createType("Ljava/io/OutputStream;"));
+ DexMethod method = factory.createMethod(clazz.type, proto, methodName);
+ MethodAccessFlags flags =
+ MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false);
+ builder.amendLibraryMethod(method, flags);
+ DexEncodedMethod build =
+ DexEncodedMethod.builder().setMethod(method).setAccessFlags(flags).build();
+ return ImmutableList.of(DexClassAndMethod.create(clazz, build));
+ }
assert !found.isEmpty()
: "Should have found a method (library specifications) for "
+ clazz.toSourceString()
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java
new file mode 100644
index 0000000..9e0908a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java
@@ -0,0 +1,395 @@
+// Copyright (c) 2021, 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.ir.optimize;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.Goto;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.Phi;
+import com.android.tools.r8.ir.code.Sub;
+import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.utils.WorkList;
+import com.google.common.collect.Sets;
+import java.util.Set;
+
+/**
+ * The NaturalIntLoopRemover detects natural loops on an integer iterator and computes the exact
+ * number of iterations if possible. If the number of iterations is known to be 1, it transforms the
+ * loop into a straight-line single iteration of the loop body.
+ *
+ * <p>This relies on the CodeRewriter to rewrite known array length upfront. Generally this can
+ * pattern match fori and for loops with any initial value and increment, but this should be
+ * extended for while loop support.
+ */
+public class NaturalIntLoopRemover {
+
+ public void run(IRCode code) {
+ boolean loopRemoved = false;
+ for (BasicBlock comparisonBlockCandidate : code.blocks) {
+ if (isComparisonBlock(comparisonBlockCandidate)) {
+ loopRemoved |= tryRemoveLoop(code, comparisonBlockCandidate.exit().asIf());
+ }
+ }
+ if (loopRemoved) {
+ code.removeAllDeadAndTrivialPhis();
+ assert code.isConsistentSSA();
+ }
+ }
+
+ private boolean isComparisonBlock(BasicBlock comparisonBlockCandidate) {
+ if (!comparisonBlockCandidate.exit().isIf()
+ || comparisonBlockCandidate.exit().asIf().isZeroTest()) {
+ return false;
+ }
+ for (Instruction instruction : comparisonBlockCandidate.getInstructions()) {
+ if (instruction.isIf()) {
+ return true;
+ }
+ if (!(instruction.isConstNumber())) {
+ return false;
+ }
+ }
+ throw new Unreachable();
+ }
+
+ private boolean tryRemoveLoop(IRCode code, If comparison) {
+ Phi loopPhi = computeLoopPhi(comparison);
+ if (loopPhi == null) {
+ return false;
+ }
+
+ NaturalIntLoopWithKnowIterations.Builder builder =
+ NaturalIntLoopWithKnowIterations.builder(comparison);
+
+ if (!analyzeLoopIterator(comparison, loopPhi, builder)) {
+ return false;
+ }
+
+ Set<BasicBlock> loopBody = computeLoopBody(builder.getBackPredecessor(), comparison.getBlock());
+ if (loopBody == null) {
+ return false;
+ }
+ if (loopBody.contains(builder.getLoopEntry())) {
+ assert false;
+ return false;
+ }
+ builder.setLoopBody(loopBody);
+
+ if (!analyzeLoopExit(loopBody, comparison, builder)) {
+ return false;
+ }
+
+ NaturalIntLoopWithKnowIterations loop = builder.build();
+
+ if (loop.has1Iteration()) {
+ loop.remove1IterationLoop(code);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Verifies the loop is well formed: the comparison on the int iterator should jump to a loop exit
+ * on one side and to the loop body on the other side.
+ */
+ private boolean analyzeLoopExit(
+ Set<BasicBlock> loopBody, If comparison, NaturalIntLoopWithKnowIterations.Builder builder) {
+ if (loopBody.contains(comparison.getTrueTarget())) {
+ if (loopBody.contains(comparison.fallthroughBlock())) {
+ return false;
+ }
+ builder.setLoop(comparison.fallthroughBlock(), comparison.getTrueTarget());
+ } else {
+ if (!loopBody.contains(comparison.fallthroughBlock())) {
+ return false;
+ }
+ builder.setLoop(comparison.getTrueTarget(), comparison.fallthroughBlock());
+ }
+ return true;
+ }
+
+ /**
+ * Analyze the int iterator so that it is initialized with a constant int value, and each
+ * iteration of the loop increment the iterator by one of the following: i + cst, cst + i or i -
+ * cst.
+ */
+ private boolean analyzeLoopIterator(
+ If comparison, Phi loopPhi, NaturalIntLoopWithKnowIterations.Builder builder) {
+ for (int i = 0; i < loopPhi.getOperands().size(); i++) {
+ Value operand = loopPhi.getOperand(i);
+ if (operand.isPhi()) {
+ return false;
+ }
+ BasicBlock predecessor = comparison.getBlock().getPredecessors().get(i);
+ if (operand.isConstNumber()) {
+ // Initial value of the int iterator.
+ if (!operand.getType().isInt() || builder.getLoopEntry() != null) {
+ return false;
+ }
+ builder.setLoopEntry(predecessor);
+ builder.setInitCounter(operand.definition.asConstNumber().getIntValue());
+ } else if (operand.definition.isAdd()) {
+ // Increment of the int iterator of type i + cst or cst + i.
+ if (builder.getBackPredecessor() != null) {
+ return false;
+ }
+ builder.setBackPredecessor(predecessor);
+ boolean metPhiOperand = false;
+ for (Value inValue : operand.definition.inValues()) {
+ if (inValue.isConstNumber() && inValue.getType().isInt()) {
+ int counterIncrement = inValue.definition.asConstNumber().getIntValue();
+ if (counterIncrement == 0 || builder.getCounterIncrement() != 0) {
+ return false;
+ }
+ builder.setCounterIncrement(counterIncrement);
+ } else if (inValue == loopPhi) {
+ if (metPhiOperand) {
+ return false;
+ }
+ metPhiOperand = true;
+ } else {
+ return false;
+ }
+ }
+ } else if (operand.definition.isSub()) {
+ // Increment of the int iterator of type i - cst.
+ if (builder.getBackPredecessor() != null) {
+ return false;
+ }
+ builder.setBackPredecessor(predecessor);
+ Sub sub = operand.definition.asSub();
+ if (sub.leftValue() != loopPhi) {
+ return false;
+ }
+ Value subValue = sub.rightValue();
+ if (subValue.isConstNumber() && subValue.getType().isInt()) {
+ assert builder.getCounterIncrement() == 0;
+ int counterIncrement = -subValue.definition.asConstNumber().getIntValue();
+ if (counterIncrement == 0) {
+ return false;
+ }
+ builder.setCounterIncrement(counterIncrement);
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ assert builder.getLoopEntry() != null;
+ assert builder.getLoopEntry().exit().isGoto();
+ assert builder.getBackPredecessor() != null;
+ assert builder.getBackPredecessor().exit().isGoto();
+ assert builder.getCounterIncrement() != 0;
+ return true;
+ }
+
+ /**
+ * Analyze the loop comparison so that it compares a loopPhi with a constant, else answers null.
+ */
+ private Phi computeLoopPhi(If comparison) {
+ Phi loopPhi = null;
+ if (comparison.rhs().isConstant() && comparison.lhs().isPhi()) {
+ loopPhi = comparison.lhs().asPhi();
+ } else if (comparison.lhs().isConstant() && comparison.rhs().isPhi()) {
+ loopPhi = comparison.rhs().asPhi();
+ }
+ if (loopPhi == null) {
+ return null;
+ }
+ if (loopPhi.getOperands().size() != 2) {
+ return null;
+ }
+ if (loopPhi.getBlock() != comparison.getBlock()) {
+ return null;
+ }
+ return loopPhi;
+ }
+
+ /**
+ * Natural int loop structure and terminology. <code>
+ * v
+ * Loop Entry
+ * int i = 0; v < < < < < < < < < < < <
+ * v v ^
+ * Comparison Block ^
+ * if (i < constant) ^
+ * v v ^
+ * Loop Exit Loop Body Entry ^
+ * v i++; ^
+ * Method Exit v ^
+ * v > > > > > > > > > > ^
+ * </code>
+ */
+ static class NaturalIntLoopWithKnowIterations {
+
+ private final int initCounter;
+ private final int counterIncrement;
+ private final If comparison;
+ private final BasicBlock loopExit;
+ private final BasicBlock loopBodyEntry;
+ private final BasicBlock backPredecessor;
+ private final Set<BasicBlock> loopBody;
+
+ NaturalIntLoopWithKnowIterations(
+ int initCounter,
+ int counterIncrement,
+ If comparison,
+ BasicBlock loopExit,
+ BasicBlock loopBodyEntry,
+ BasicBlock backPredecessor,
+ Set<BasicBlock> loopBody) {
+ this.initCounter = initCounter;
+ this.counterIncrement = counterIncrement;
+ this.comparison = comparison;
+ this.loopExit = loopExit;
+ this.loopBodyEntry = loopBodyEntry;
+ this.backPredecessor = backPredecessor;
+ this.loopBody = loopBody;
+ }
+
+ static class Builder {
+
+ private int initCounter;
+ private int counterIncrement;
+ private final If comparison;
+ private BasicBlock loopExit;
+ private BasicBlock loopBodyEntry;
+ private BasicBlock loopEntry;
+ private BasicBlock backPredecessor;
+ private Set<BasicBlock> loopBody;
+
+ Builder(If comparison) {
+ this.comparison = comparison;
+ }
+
+ public void setInitCounter(int initCounter) {
+ this.initCounter = initCounter;
+ }
+
+ public int getCounterIncrement() {
+ return counterIncrement;
+ }
+
+ public void setCounterIncrement(int counterIncrement) {
+ this.counterIncrement = counterIncrement;
+ }
+
+ public BasicBlock getLoopEntry() {
+ return loopEntry;
+ }
+
+ public void setLoopEntry(BasicBlock loopEntry) {
+ this.loopEntry = loopEntry;
+ }
+
+ public BasicBlock getBackPredecessor() {
+ return backPredecessor;
+ }
+
+ public void setBackPredecessor(BasicBlock backPredecessor) {
+ this.backPredecessor = backPredecessor;
+ }
+
+ public void setLoop(BasicBlock loopExit, BasicBlock loopBodyEntry) {
+ this.loopExit = loopExit;
+ this.loopBodyEntry = loopBodyEntry;
+ }
+
+ public void setLoopBody(Set<BasicBlock> loopBody) {
+ this.loopBody = loopBody;
+ }
+
+ public NaturalIntLoopWithKnowIterations build() {
+ return new NaturalIntLoopWithKnowIterations(
+ initCounter,
+ counterIncrement,
+ comparison,
+ loopExit,
+ loopBodyEntry,
+ backPredecessor,
+ loopBody);
+ }
+ }
+
+ static Builder builder(If comparison) {
+ return new Builder(comparison);
+ }
+
+ private BasicBlock target(int phiValue) {
+ if (comparison.rhs().isConstNumber()) {
+ int comp = comparison.rhs().getDefinition().asConstNumber().getIntValue();
+ return comparison.targetFromCondition(Integer.signum(phiValue - comp));
+ }
+ int comp = comparison.lhs().getDefinition().asConstNumber().getIntValue();
+ return comparison.targetFromCondition(Integer.signum(comp - phiValue));
+ }
+
+ public boolean has1Iteration() {
+ return target(initCounter) == loopBodyEntry
+ && target(initCounter + counterIncrement) == loopExit;
+ }
+
+ private void remove1IterationLoop(IRCode code) {
+ BasicBlock comparisonBlock = comparison.getBlock();
+ updatePhis(comparisonBlock);
+ patchControlFlow(code, comparisonBlock);
+ }
+
+ private void patchControlFlow(IRCode code, BasicBlock comparisonBlock) {
+ assert loopExit.getPhis().isEmpty(); // Edges should be split.
+ comparisonBlock.replaceLastInstruction(new Goto(loopBodyEntry), code);
+ comparisonBlock.removeSuccessor(loopExit);
+
+ backPredecessor.replaceSuccessor(comparisonBlock, loopExit);
+ backPredecessor.replaceLastInstruction(new Goto(loopExit), code);
+ comparisonBlock.removePredecessor(backPredecessor, Sets.newIdentityHashSet());
+ loopExit.replacePredecessor(comparisonBlock, backPredecessor);
+ }
+
+ private void updatePhis(BasicBlock comparisonBlock) {
+ int backIndex = comparisonBlock.getPredecessors().indexOf(backPredecessor);
+ for (Phi phi : comparisonBlock.getPhis()) {
+ Value loopEntryValue = phi.getOperand(1 - backIndex);
+ Value loopExitValue = phi.getOperand(backIndex);
+ for (Instruction uniqueUser : phi.uniqueUsers()) {
+ if (loopBody.contains(uniqueUser.getBlock())) {
+ uniqueUser.replaceValue(phi, loopEntryValue);
+ } else {
+ uniqueUser.replaceValue(phi, loopExitValue);
+ }
+ }
+ for (Phi phiUser : phi.uniquePhiUsers()) {
+ if (loopBody.contains(phiUser.getBlock())) {
+ phiUser.replaceOperand(phi, loopEntryValue);
+ } else {
+ phiUser.replaceOperand(phi, loopExitValue);
+ }
+ }
+ }
+ }
+ }
+
+ private Set<BasicBlock> computeLoopBody(BasicBlock backPredecessor, BasicBlock comparisonBlock) {
+ WorkList<BasicBlock> workList = WorkList.newIdentityWorkList();
+ workList.addIfNotSeen(backPredecessor);
+ workList.markAsSeen(comparisonBlock);
+ while (!workList.isEmpty()) {
+ BasicBlock basicBlock = workList.next();
+ if (basicBlock.isEntry()) {
+ // This can happen in loops with multiple entries (Duff device, etc.).
+ // Such loops are not generated by javac so we assume they are uncommon.
+ return null;
+ }
+ for (BasicBlock predecessor : basicBlock.getPredecessors()) {
+ workList.addIfNotSeen(predecessor);
+ }
+ }
+ return workList.getSeenSet();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
index e515c08..d3f9395 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.code.Invoke;
+import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.collections.BidirectionalOneToManyRepresentativeHashMap;
@@ -27,7 +28,9 @@
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToManyRepresentativeMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -148,7 +151,7 @@
}
public void move(DexMethod from, DexMethod to, boolean fromStatic, boolean toStatic) {
- move(from, to, fromStatic, toStatic, 0);
+ move(from, to, fromStatic, toStatic, Collections.emptyList());
}
public RewrittenPrototypeDescription move(
@@ -156,7 +159,7 @@
DexMethod to,
boolean fromStatic,
boolean toStatic,
- int numberOfExtraNullParameters) {
+ List<ExtraUnusedNullParameter> extraUnusedNullParameters) {
assert from != to;
newMethodSignatures.put(from, to);
int offsetDiff = 0;
@@ -167,12 +170,14 @@
if (fromStatic != toStatic) {
assert toStatic;
offsetDiff = 1;
- builder.addArgumentInfo(
- 0,
- RewrittenTypeInfo.builder()
- .setOldType(from.getHolderType())
- .setNewType(to.getParameter(0))
- .build());
+ builder
+ .addArgumentInfo(
+ 0,
+ RewrittenTypeInfo.builder()
+ .setOldType(from.getHolderType())
+ .setNewType(to.getParameter(0))
+ .build())
+ .setIsConvertedToStaticMethod();
}
for (int i = 0; i < from.getParameters().size(); i++) {
DexType fromType = from.getParameter(i);
@@ -192,7 +197,7 @@
.build();
RewrittenPrototypeDescription prototypeChanges =
RewrittenPrototypeDescription.createForRewrittenTypes(returnInfo, builder.build())
- .withExtraUnusedNullParameters(numberOfExtraNullParameters);
+ .withExtraParameters(extraUnusedNullParameters);
prototypeChangesPerMethod.put(to, prototypeChanges);
return prototypeChanges;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index c054329..3c8bdbc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -37,6 +37,7 @@
import com.android.tools.r8.ir.code.NewUnboxedEnumInstance;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.conversion.OneTimeMethodProcessor;
import com.android.tools.r8.ir.optimize.enums.EnumDataMap.EnumData;
@@ -575,11 +576,12 @@
method.getName().toString() + (method.isNonPrivateVirtualMethod() ? "$enumunboxing$" : "");
DexMethod newMethod = factory.createMethod(method.getHolderType(), newProto, newMethodName);
newMethod = ensureUniqueMethod(method, newMethod);
- int numberOfExtraNullParameters = newMethod.getArity() - method.getReference().getArity();
+ List<ExtraUnusedNullParameter> extraUnusedNullParameters =
+ ExtraUnusedNullParameter.computeExtraUnusedNullParameters(method.getReference(), newMethod);
boolean isStatic = method.isStatic();
RewrittenPrototypeDescription prototypeChanges =
lensBuilder.move(
- method.getReference(), newMethod, isStatic, isStatic, numberOfExtraNullParameters);
+ method.getReference(), newMethod, isStatic, isStatic, extraUnusedNullParameters);
return method.toTypeSubstitutedMethod(
newMethod,
builder ->
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index bdda2fe..98057dd 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.SourceFileEnvironment;
import com.android.tools.r8.cf.CfVersion;
+import com.android.tools.r8.debuginfo.DebugRepresentation;
import com.android.tools.r8.dex.ApplicationWriter;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.errors.CodeSizeOverflowDiagnostic;
@@ -137,7 +138,12 @@
if (options.proguardMapConsumer != null) {
proguardMapId =
runAndWriteMap(
- inputApp, appView, namingLens, application.timing, OriginalSourceFiles.fromClasses());
+ inputApp,
+ appView,
+ namingLens,
+ application.timing,
+ OriginalSourceFiles.fromClasses(),
+ DebugRepresentation.none(options));
marker.setPgMapId(proguardMapId.getId());
}
Optional<String> markerString =
diff --git a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
index 433349e..f24cac2 100644
--- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
@@ -80,6 +80,9 @@
public void run(ExecutorService executorService) throws ExecutionException {
// Collect all visibility bridges to remove.
+ if (!appView.options().enableVisibilityBridgeRemoval) {
+ return;
+ }
ConcurrentHashMap<DexProgramClass, Set<DexEncodedMethod>> visibilityBridgesToRemove =
new ConcurrentHashMap<>();
processItems(
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
index 958c85b..fc48b5d 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
@@ -49,9 +49,6 @@
return prototypeChanges.getOrDefault(method, RewrittenPrototypeDescription.none());
}
- public boolean isAffected(DexMethod method) {
- return method != getPreviousMethodSignature(method) || hasPrototypeChanges(method);
- }
@Override
protected boolean isLegitimateToHaveEmptyMappings() {
@@ -104,13 +101,12 @@
@Override
protected Type mapInvocationType(DexMethod newMethod, DexMethod originalMethod, Type type) {
- if (!type.isStatic() && hasPrototypeChanges(newMethod)) {
- RewrittenPrototypeDescription prototypeChanges = getPrototypeChanges(newMethod);
- if (prototypeChanges.getArgumentInfoCollection().isArgumentRemoved(0)) {
- return Type.STATIC;
- }
- }
- return super.mapInvocationType(newMethod, originalMethod, type);
+ return hasPrototypeChanges(newMethod)
+ && getPrototypeChanges(newMethod)
+ .getArgumentInfoCollection()
+ .isConvertedToStaticMethod()
+ ? Type.STATIC
+ : super.mapInvocationType(newMethod, originalMethod, type);
}
public static class Builder {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
index 24d6e46..cca53b7 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -1021,8 +1021,10 @@
&& method.getOptimizationInfo().getUnusedArguments().get(0)
&& ParameterRemovalUtils.canRemoveUnusedParametersFrom(appView, method)
&& ParameterRemovalUtils.canRemoveUnusedParameter(appView, method, 0)) {
- parameterChangesBuilder.addArgumentInfo(
- 0, RemovedReceiverInfo.Builder.create().setType(method.getHolderType()).build());
+ parameterChangesBuilder
+ .addArgumentInfo(
+ 0, RemovedReceiverInfo.Builder.create().setType(method.getHolderType()).build())
+ .setIsConvertedToStaticMethod();
}
CallSiteOptimizationInfo optimizationInfo = method.getOptimizationInfo().getArgumentInfos();
diff --git a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java
index b1237ed..0213d86 100644
--- a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizer.java
@@ -15,9 +15,11 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollection;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.KeepMethodInfo;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.MapUtils;
@@ -52,9 +54,7 @@
}
public void run(ExecutorService executorService, Timing timing) throws ExecutionException {
- if (options.testing.enableExperimentalProtoNormalization) {
- timing.time("Proto normalization", () -> run(executorService));
- }
+ timing.time("Proto normalization", () -> run(executorService));
}
private void run(ExecutorService executorService) throws ExecutionException {
@@ -280,9 +280,24 @@
}
private boolean isUnoptimizable(ProgramMethod method) {
- // TODO(b/195112263): This is incomplete.
- return appView.getKeepInfo(method).isPinned(options)
- || method.getDefinition().isLibraryMethodOverride().isPossiblyTrue();
+ KeepMethodInfo keepInfo = appView.getKeepInfo(method);
+ if (!keepInfo.isParameterReorderingAllowed(options)
+ || method.getDefinition().isLibraryMethodOverride().isPossiblyTrue()) {
+ return true;
+ }
+ AppInfoWithLiveness appInfo = appView.appInfo();
+ if (appInfo.isBootstrapMethod(method)) {
+ return true;
+ }
+ ObjectAllocationInfoCollection objectAllocationInfoCollection =
+ appInfo.getObjectAllocationInfoCollection();
+ if (method.getHolder().isInterface()
+ && method.getDefinition().isAbstract()
+ && objectAllocationInfoCollection.isImmediateInterfaceOfInstantiatedLambda(
+ method.getHolder())) {
+ return true;
+ }
+ return false;
}
static class GlobalReservationState {
@@ -377,6 +392,7 @@
do {
DexString newMethodName = dexItemFactory.createString(newMethodBaseName + "$" + index);
newMethodSignature = newMethodSignature.withName(newMethodName);
+ index++;
} while (newMethodSignatures.containsValue(newMethodSignature));
}
if (reserve) {
diff --git a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java
index bfeef49..1ce0703 100644
--- a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java
@@ -56,8 +56,11 @@
}
@Override
- public DexField getRenamedFieldSignature(DexField originalField, GraphLens codeLens) {
- return originalField;
+ public DexField getRenamedFieldSignature(DexField originalField, GraphLens applied) {
+ if (this == applied) {
+ return originalField;
+ }
+ return getPrevious().getRenamedFieldSignature(originalField);
}
@Override
@@ -65,7 +68,7 @@
if (this == applied) {
return originalMethod;
}
- return newMethodSignatures.getOrDefault(originalMethod, originalMethod);
+ return getNextMethodSignature(getPrevious().getRenamedMethodSignature(originalMethod));
}
@Override
@@ -98,14 +101,18 @@
protected MethodLookupResult internalDescribeLookupMethod(
MethodLookupResult previous, DexMethod context) {
DexMethod methodSignature = previous.getReference();
- DexMethod newMethodSignature = getRenamedMethodSignature(methodSignature);
+ DexMethod newMethodSignature = getNextMethodSignature(methodSignature);
if (methodSignature == newMethodSignature) {
return previous;
}
assert !previous.hasReboundReference();
return MethodLookupResult.builder(this)
.setPrototypeChanges(
- previous.getPrototypeChanges().combine(prototypeChanges.get(newMethodSignature)))
+ previous
+ .getPrototypeChanges()
+ .combine(
+ prototypeChanges.getOrDefault(
+ newMethodSignature, RewrittenPrototypeDescription.none())))
.setReference(newMethodSignature)
.setType(previous.getType())
.build();
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 91f926c..14a84d5 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.shaking;
import static com.android.tools.r8.dex.Constants.TEMPORARY_INSTANCE_INITIALIZER_PREFIX;
+import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.ir.code.Invoke.Type.DIRECT;
import static com.android.tools.r8.ir.code.Invoke.Type.STATIC;
@@ -720,7 +721,7 @@
new VerticalClassMergerTreeFixer(
appView, lensBuilder, verticallyMergedClasses, synthesizedBridges)
.fixupTypeReferences();
- KeepInfoCollection keepInfo = appView.appInfo().getKeepInfo();
+ KeepInfoCollection keepInfo = appView.getKeepInfo();
keepInfo.mutate(
mutator ->
mutator.removeKeepInfoForMergedClasses(
@@ -729,6 +730,26 @@
assert lens != null;
assert verifyGraphLens(lens);
+
+ // Rewrite collections using the lens.
+ appView.rewriteWithLens(lens);
+
+ // Copy keep info to newly synthesized methods.
+ keepInfo.mutate(
+ mutator -> {
+ for (SynthesizedBridgeCode synthesizedBridge : synthesizedBridges) {
+ ProgramMethod bridge =
+ asProgramMethodOrNull(appView.definitionFor(synthesizedBridge.method));
+ ProgramMethod target =
+ asProgramMethodOrNull(appView.definitionFor(synthesizedBridge.invocationTarget));
+ if (bridge != null && target != null) {
+ mutator.joinMethod(bridge, info -> info.merge(appView.getKeepInfo(target).joiner()));
+ continue;
+ }
+ assert false;
+ }
+ });
+
return lens;
}
@@ -1137,7 +1158,10 @@
}
deferredRenamings.map(virtualMethod.getReference(), shadowedBy.getReference());
- deferredRenamings.recordMove(virtualMethod.getReference(), resultingMethod.getReference());
+ deferredRenamings.recordMove(
+ virtualMethod.getReference(),
+ resultingMethod.getReference(),
+ resultingMethod.isStatic());
}
if (abortMerge) {
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
index 166ed69..05837f0 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
+import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.utils.IterableUtils;
@@ -21,6 +22,7 @@
import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import java.util.Collection;
@@ -66,6 +68,7 @@
contextualVirtualToDirectMethodMaps;
private Set<DexMethod> mergedMethods;
private final Map<DexMethod, DexMethod> originalMethodSignaturesForBridges;
+ private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChanges;
private VerticalClassMergerGraphLens(
AppView<?> appView,
@@ -76,13 +79,15 @@
Map<DexType, Map<DexMethod, GraphLensLookupResultProvider>>
contextualVirtualToDirectMethodMaps,
BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> newMethodSignatures,
- Map<DexMethod, DexMethod> originalMethodSignaturesForBridges) {
+ Map<DexMethod, DexMethod> originalMethodSignaturesForBridges,
+ Map<DexMethod, RewrittenPrototypeDescription> prototypeChanges) {
super(appView, fieldMap, methodMap, mergedClasses.getForwardMap(), newMethodSignatures);
this.appView = appView;
this.mergedClasses = mergedClasses;
this.contextualVirtualToDirectMethodMaps = contextualVirtualToDirectMethodMaps;
this.mergedMethods = mergedMethods;
this.originalMethodSignaturesForBridges = originalMethodSignaturesForBridges;
+ this.prototypeChanges = prototypeChanges;
}
@Override
@@ -135,6 +140,13 @@
}
@Override
+ protected RewrittenPrototypeDescription internalDescribePrototypeChanges(
+ RewrittenPrototypeDescription prototypeChanges, DexMethod method) {
+ return prototypeChanges.combine(
+ this.prototypeChanges.getOrDefault(method, RewrittenPrototypeDescription.none()));
+ }
+
+ @Override
public DexMethod getPreviousMethodSignature(DexMethod method) {
return super.getPreviousMethodSignature(
originalMethodSignaturesForBridges.getOrDefault(method, method));
@@ -174,6 +186,8 @@
newMethodSignatures = BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
private final Map<DexMethod, DexMethod> originalMethodSignaturesForBridges =
new IdentityHashMap<>();
+ private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChanges =
+ new IdentityHashMap<>();
private final Map<DexProto, DexProto> cache = new IdentityHashMap<>();
@@ -231,6 +245,11 @@
entry.getValue(),
builder.getMethodSignatureAfterClassMerging(entry.getKey(), mergedClasses));
}
+ builder.prototypeChanges.forEach(
+ (method, prototypeChangesForMethod) ->
+ newBuilder.prototypeChanges.put(
+ builder.getMethodSignatureAfterClassMerging(method, mergedClasses),
+ prototypeChangesForMethod));
return newBuilder;
}
@@ -248,7 +267,8 @@
mergedMethodsBuilder.build(),
contextualVirtualToDirectMethodMaps,
newMethodSignatures,
- originalMethodSignaturesForBridges);
+ originalMethodSignaturesForBridges,
+ prototypeChanges);
}
private DexField getFieldSignatureAfterClassMerging(
@@ -335,7 +355,22 @@
}
public void recordMove(DexMethod from, DexMethod to) {
+ recordMove(from, to, false);
+ }
+
+ public void recordMove(DexMethod from, DexMethod to, boolean isStaticized) {
newMethodSignatures.put(from, to);
+ if (isStaticized) {
+ RewrittenPrototypeDescription prototypeChangesForMethod =
+ RewrittenPrototypeDescription.create(
+ ImmutableList.of(),
+ null,
+ ArgumentInfoCollection.builder()
+ .setArgumentInfosSize(to.getParameters().size())
+ .setIsConvertedToStaticMethod()
+ .build());
+ prototypeChanges.put(to, prototypeChangesForMethod);
+ }
}
public void recordCreationOfBridgeMethod(DexMethod from, DexMethod to) {
@@ -385,6 +420,7 @@
}
}
});
+ prototypeChanges.putAll(builder.prototypeChanges);
originalMethodSignaturesForBridges.putAll(builder.originalMethodSignaturesForBridges);
for (DexType context : builder.contextualVirtualToDirectMethodMaps.keySet()) {
Map<DexMethod, GraphLensLookupResultProvider> current =
diff --git a/src/main/java/com/android/tools/r8/utils/ClassMap.java b/src/main/java/com/android/tools/r8/utils/ClassMap.java
index 506a990..915a2f7 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassMap.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassMap.java
@@ -163,6 +163,15 @@
return classes.keySet();
}
+ public Iterable<DexType> getAllClassProviderTypes() {
+ ClassProvider<T> theClassProvider = classProvider.get();
+ if (theClassProvider != null) {
+ return theClassProvider.collectTypes();
+ }
+ throw new CompilationError(
+ "Cannot access all types since the classProvider is no longer available");
+ }
+
/**
* Forces loading of all the classes satisfying the criteria specified.
* <p>
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 3fec28a..2b8d72a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -298,6 +298,7 @@
public boolean readDebugSetFileEvent = false;
public boolean disableL8AnnotationRemoval =
System.getProperty("com.android.tools.r8.disableL8AnnotationRemoval") != null;
+ public boolean enableVisibilityBridgeRemoval = true;
public int callGraphLikelySpuriousCallEdgeThreshold = 50;
@@ -895,7 +896,13 @@
return;
}
try {
- machineDesugaredLibrarySpecification = specification.toMachineSpecification(this, app);
+ // TODO(b/221224178): Move the timing to top level timing in D8, R8 and L8.
+ Timing timing = Timing.create("Desugared library specification conversion", this);
+ machineDesugaredLibrarySpecification =
+ specification.toMachineSpecification(this, app, timing);
+ if (printTimes) {
+ timing.report();
+ }
} catch (IOException e) {
reporter.error(new ExceptionDiagnostic(e, Origin.unknown()));
}
@@ -907,8 +914,13 @@
if (specification.isEmpty()) {
return;
}
+ // TODO(b/221224178): Move the timing to top level timing in D8, R8 and L8.
+ Timing timing = Timing.create("Desugared library specification conversion", this);
machineDesugaredLibrarySpecification =
- specification.toMachineSpecification(this, library, desugaredJDKLib);
+ specification.toMachineSpecification(this, library, timing, desugaredJDKLib);
+ if (printTimes) {
+ timing.report();
+ }
}
// Contains flags describing library desugaring.
@@ -1658,11 +1670,11 @@
public boolean enableEnumUnboxingDebugLogs = false;
public boolean forceRedundantConstNumberRemoval = false;
public boolean enableExperimentalDesugaredLibraryKeepRuleGenerator = false;
- public boolean enableExperimentalProtoNormalization = false;
public boolean invertConditionals = false;
public boolean placeExceptionalBlocksLast = false;
public boolean dontCreateMarkerInD8 = false;
public boolean forceJumboStringProcessing = false;
+ public boolean forcePcBasedEncoding = false;
public Set<Inliner.Reason> validInliningReasons = null;
public boolean noLocalsTableOnInput = false;
public boolean forceNameReflectionOptimization = false;
@@ -1884,7 +1896,7 @@
}
public boolean canUseDexPc2PcAsDebugInformation() {
- return lineNumberOptimization == LineNumberOptimization.ON;
+ return isGeneratingDex() && lineNumberOptimization == LineNumberOptimization.ON;
}
public boolean canUseNativeDexPcInsteadOfDebugInfo() {
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 50eeb68..22932f6 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfPosition;
+import com.android.tools.r8.debuginfo.DebugRepresentation.DebugRepresentationPredicate;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -334,14 +335,21 @@
AppView<?> appView,
NamingLens namingLens,
Timing timing,
- OriginalSourceFiles originalSourceFiles) {
+ OriginalSourceFiles originalSourceFiles,
+ DebugRepresentationPredicate representation) {
assert appView.options().proguardMapConsumer != null;
// When line number optimization is turned off the identity mapping for line numbers is
// used. We still run the line number optimizer to collect line numbers and inline frame
// information for the mapping file.
timing.begin("Line number remapping");
ClassNameMapper mapper =
- run(appView, appView.appInfo().app(), inputApp, namingLens, originalSourceFiles);
+ run(
+ appView,
+ appView.appInfo().app(),
+ inputApp,
+ namingLens,
+ originalSourceFiles,
+ representation);
timing.end();
timing.begin("Write proguard map");
ProguardMapId mapId = ProguardMapSupplier.create(mapper, appView.options()).writeProguardMap();
@@ -465,9 +473,12 @@
DexApplication application,
AndroidApp inputApp,
NamingLens namingLens,
- OriginalSourceFiles originalSourceFiles) {
+ OriginalSourceFiles originalSourceFiles,
+ DebugRepresentationPredicate representation) {
// For finding methods in kotlin files based on SourceDebugExtensions, we use a line method map.
// We create it here to ensure it is only reading class files once.
+ // TODO(b/220999985): Make this threaded per virtual file. Possibly pull the kotlin line mapping
+ // onto main thread before threading.
CfLineToMethodMapper cfLineToMethodMapper = new CfLineToMethodMapper(inputApp);
ClassNameMapper.Builder classNameMapperBuilder = ClassNameMapper.builder();
@@ -560,7 +571,7 @@
List<MappedPosition> mappedPositions;
Code code = method.getCode();
boolean canUseDexPc =
- appView.options().canUseDexPc2PcAsDebugInformation() && methods.size() == 1;
+ methods.size() == 1 && representation.useDexPcEncoding(clazz, method);
if (code != null) {
if (code.isDexCode() && doesContainPositions(code.asDexCode())) {
if (canUseDexPc) {
@@ -910,7 +921,7 @@
});
}
- private static IdentityHashMap<DexString, List<DexEncodedMethod>> groupMethodsByRenamedName(
+ public static IdentityHashMap<DexString, List<DexEncodedMethod>> groupMethodsByRenamedName(
GraphLens graphLens, NamingLens namingLens, DexProgramClass clazz) {
IdentityHashMap<DexString, List<DexEncodedMethod>> methodsByRenamedName =
new IdentityHashMap<>(clazz.getMethodCollection().size());
@@ -943,7 +954,7 @@
return false;
}
- private static boolean doesContainPositions(DexCode dexCode) {
+ public static boolean doesContainPositions(DexCode dexCode) {
DexDebugInfo debugInfo = dexCode.getDebugInfo();
if (debugInfo == null) {
return false;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java b/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java
index bff70f5..387788a 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java
@@ -196,7 +196,10 @@
CheckCast.builder()
.setCastType(castType)
.setObject(operand)
- .setFreshOutValue(code, castType.toTypeElement(appView), operand.getLocalInfo())
+ .setFreshOutValue(
+ code,
+ castType.toTypeElement(appView, operand.getType().nullability()),
+ operand.getLocalInfo())
.setPosition(rewrittenUser)
.build();
if (block.hasCatchHandlers()) {
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 5b735b1..352e12b 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -2022,8 +2022,9 @@
System.out.println("Running on 10.0.0 is disabled, see b/144966342");
continue;
}
- if (vm.getVersion() == DexVm.Version.V12_0_0) {
- System.out.println("Running on 12.0.0 is disabled, see b/197078995");
+ if (vm.getVersion() == DexVm.Version.V12_0_0
+ || vm.getVersion() == DexVm.Version.V13_MASTER) {
+ System.out.println("Running on 12.0.0 or V13_MASTER is disabled, see b/197078995");
continue;
}
vms.add(new DexRuntime(vm));
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index f695dbb..ec8d314 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -89,6 +89,10 @@
Version.V12_0_0,
// TODO(120402963) Triage.
ImmutableList.of("invokecustom-with-shrinking", "invokecustom2-with-shrinking"))
+ .put(
+ Version.V13_MASTER,
+ // TODO(120402963) Triage.
+ ImmutableList.of("invokecustom-with-shrinking", "invokecustom2-with-shrinking"))
.put(Version.DEFAULT, ImmutableList.of())
.build();
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index fb17345..dc4d111 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -314,6 +314,10 @@
return compareTo(other) == 0;
}
+ public boolean isEqualToOneOf(Version... versions) {
+ return Arrays.stream(versions).anyMatch(this::isEqualTo);
+ }
+
public boolean isNewerThan(Version other) {
return compareTo(other) > 0;
}
@@ -1288,7 +1292,7 @@
R8.runForTesting(command.getInputApp(), internalOptions);
if (benchmarkResults != null) {
long end = System.nanoTime();
- benchmarkResults.addRuntimeRawResult(end - start);
+ benchmarkResults.addRuntimeResult(end - start);
}
}
@@ -1368,20 +1372,20 @@
BenchmarkResults benchmarkResults)
throws CompilationFailedException {
AndroidAppConsumers compatSink = new AndroidAppConsumers(builder);
+ long start = 0;
+ if (benchmarkResults != null) {
+ start = System.nanoTime();
+ }
D8Command command = builder.build();
InternalOptions options = command.getInternalOptions();
if (optionsConsumer != null) {
ExceptionUtils.withD8CompilationHandler(
options.reporter, () -> optionsConsumer.accept(options));
}
- long start = 0;
- if (benchmarkResults != null) {
- start = System.nanoTime();
- }
D8.runForTesting(command.getInputApp(), options);
if (benchmarkResults != null) {
long end = System.nanoTime();
- benchmarkResults.addRuntimeRawResult(end - start);
+ benchmarkResults.addRuntimeResult(end - start);
}
return compatSink.build();
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java
index 3753d7f..c7a7e37 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java
@@ -32,7 +32,7 @@
@Test
public void testBenchmarks() throws Exception {
- config.run(temp);
+ config.run(new BenchmarkEnvironment(config, temp, false));
}
public static BenchmarkRunner runner(BenchmarkConfig config) {
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollection.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollection.java
index da0c335..c741f27 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollection.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollection.java
@@ -5,6 +5,7 @@
import static java.util.Collections.emptyList;
+import com.android.tools.r8.benchmarks.desugaredlib.LegacyDesugaredLibraryBenchmark;
import com.android.tools.r8.benchmarks.helloworld.HelloWorldBenchmark;
import java.io.IOException;
import java.util.ArrayList;
@@ -43,6 +44,7 @@
BenchmarkCollection collection = new BenchmarkCollection();
// Every benchmark that should be active on golem must be setup in this method.
HelloWorldBenchmark.configs().forEach(collection::addBenchmark);
+ LegacyDesugaredLibraryBenchmark.configs().forEach(collection::addBenchmark);
return collection;
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollectionPrinter.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollectionPrinter.java
index b7786f7..c1fbad4 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollectionPrinter.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkCollectionPrinter.java
@@ -110,7 +110,6 @@
throws IOException {
// Common properties that must be consistent among all the benchmark variants.
String suite = BenchmarkConfig.getCommonSuite(benchmarkVariants).getDartName();
- boolean hasWarmup = BenchmarkConfig.getCommonTimeWarmupRuns(benchmarkVariants);
List<String> metrics =
new ArrayList<>(
ListUtils.map(
@@ -118,12 +117,12 @@
metrics.sort(String::compareTo);
printSemi("final name = " + quote(benchmarkName));
printSemi("final metrics = " + StringUtils.join(", ", metrics, BraceType.SQUARE));
- printSemi("final group = new GroupBenchmark(name + \"Group\", metrics)");
+ printSemi("final benchmark = new StandardBenchmark(name, metrics)");
for (BenchmarkConfig benchmark : benchmarkVariants) {
scopeBraces(
() -> {
printSemi("final target = " + quote(benchmark.getTarget().getGolemName()));
- printSemi("final options = group.addTargets(noImplementation, [target])");
+ printSemi("final options = benchmark.addTargets(noImplementation, [target])");
printSemi("options.cpus = cpus");
printSemi("options.isScript = true");
printSemi("options.fromRevision = " + benchmark.getFromRevision());
@@ -139,15 +138,16 @@
+ " --benchmark "
+ benchmark.getName())));
printSemi("options.resources.add(openjdk)");
+ for (BenchmarkDependency dependency : benchmark.getDependencies()) {
+ scopeBraces(
+ () -> {
+ addGolemResource("dependency", dependency.getTarball());
+ printSemi("options.resources.add(dependency)");
+ });
+ }
});
}
- printSemi("group.addBenchmark(name, metrics)");
printSemi(suite + ".addBenchmark(name)");
- if (hasWarmup) {
- printSemi("final warmupName = name + \"Warmup\"");
- printSemi("group.addBenchmark(warmupName, [Metric.RunTimeRaw])");
- printSemi(suite + ".addBenchmark(warmupName)");
- }
}
private void addGolemResource(String name, Path tarball) throws IOException {
@@ -173,7 +173,7 @@
}
private static Path getJdkHome() throws IOException {
- ProcessBuilder builder = new ProcessBuilder("python", "tools/jdk.py");
+ ProcessBuilder builder = new ProcessBuilder("python3", "tools/jdk.py");
ProcessResult result = ToolHelper.runProcess(builder, QUIET);
if (result.exitCode != 0) {
throw new BenchmarkConfigError("Unexpected failure to determine jdk home: " + result);
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java
index c64dbd2..6daaa7a 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java
@@ -5,10 +5,11 @@
import com.android.tools.r8.errors.Unreachable;
import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.junit.rules.TemporaryFolder;
public class BenchmarkConfig {
@@ -38,10 +39,6 @@
return getConsistentRepresentative(variants).getSuite();
}
- public static boolean getCommonTimeWarmupRuns(List<BenchmarkConfig> variants) {
- return getConsistentRepresentative(variants).hasTimeWarmupRuns();
- }
-
private static BenchmarkConfig getConsistentRepresentative(List<BenchmarkConfig> variants) {
if (variants.isEmpty()) {
throw new BenchmarkConfigError("Unexpected attempt to check consistency of empty collection");
@@ -60,10 +57,9 @@
private BenchmarkTarget target = null;
private Set<BenchmarkMetric> metrics = new HashSet<>();
private BenchmarkSuite suite = BenchmarkSuite.getDefault();
+ private Collection<BenchmarkDependency> dependencies = new ArrayList<>();
private int fromRevision = -1;
- private boolean timeWarmupRuns = false;
-
private Builder() {}
public BenchmarkConfig build() {
@@ -85,11 +81,14 @@
if (fromRevision < 0) {
throw new Unreachable("Benchmark must specify from which golem revision it is valid");
}
- if (timeWarmupRuns && !metrics.contains(BenchmarkMetric.RunTimeRaw)) {
- throw new Unreachable("Benchmark with warmup time must measure RunTimeRaw");
- }
return new BenchmarkConfig(
- name, method, target, ImmutableSet.copyOf(metrics), suite, fromRevision, timeWarmupRuns);
+ name,
+ method,
+ target,
+ ImmutableSet.copyOf(metrics),
+ suite,
+ fromRevision,
+ dependencies);
}
public Builder setName(String name) {
@@ -107,7 +106,7 @@
return this;
}
- public Builder measureRunTimeRaw() {
+ public Builder measureRunTime() {
metrics.add(BenchmarkMetric.RunTimeRaw);
return this;
}
@@ -117,6 +116,11 @@
return this;
}
+ public Builder measureWarmup() {
+ metrics.add(BenchmarkMetric.StartupTime);
+ return this;
+ }
+
public Builder setSuite(BenchmarkSuite suite) {
this.suite = suite;
return this;
@@ -127,8 +131,8 @@
return this;
}
- public Builder timeWarmupRuns() {
- this.timeWarmupRuns = true;
+ public Builder addDependency(BenchmarkDependency dependency) {
+ dependencies.add(dependency);
return this;
}
}
@@ -141,8 +145,8 @@
private final BenchmarkMethod method;
private final ImmutableSet<BenchmarkMetric> metrics;
private final BenchmarkSuite suite;
+ private final Collection<BenchmarkDependency> dependencies;
private final int fromRevision;
- private final boolean timeWarmupRuns;
private BenchmarkConfig(
String name,
@@ -151,13 +155,13 @@
ImmutableSet<BenchmarkMetric> metrics,
BenchmarkSuite suite,
int fromRevision,
- boolean timeWarmupRuns) {
+ Collection<BenchmarkDependency> dependencies) {
this.id = new BenchmarkIdentifier(name, target);
this.method = benchmarkMethod;
this.metrics = metrics;
this.suite = suite;
this.fromRevision = fromRevision;
- this.timeWarmupRuns = timeWarmupRuns;
+ this.dependencies = dependencies;
}
public BenchmarkIdentifier getIdentifier() {
@@ -168,13 +172,6 @@
return id.getName();
}
- public String getWarmupName() {
- if (!timeWarmupRuns) {
- throw new BenchmarkConfigError("Invalid attempt at getting warmup benchmark name");
- }
- return getName() + "Warmup";
- }
-
public BenchmarkTarget getTarget() {
return id.getTarget();
}
@@ -196,11 +193,15 @@
}
public boolean hasTimeWarmupRuns() {
- return timeWarmupRuns;
+ return hasMetric(BenchmarkMetric.StartupTime);
}
- public void run(TemporaryFolder temp) throws Exception {
- method.run(this, temp);
+ public Collection<BenchmarkDependency> getDependencies() {
+ return dependencies;
+ }
+
+ public void run(BenchmarkEnvironment environment) throws Exception {
+ method.run(environment);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkDependency.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkDependency.java
new file mode 100644
index 0000000..f59ebb6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkDependency.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2022, 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.benchmarks;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class BenchmarkDependency {
+
+ public static BenchmarkDependency getRuntimeJarJava8() {
+ return new BenchmarkDependency("openjdk-rt-1.8", Paths.get("third_party", "openjdk"));
+ }
+
+ public static BenchmarkDependency getAndroidJar30() {
+ return new BenchmarkDependency("lib-v30", Paths.get("third_party", "android_jar"));
+ }
+
+ // Directory name of the dependency.
+ private final String directoryName;
+
+ // Location in the R8 source tree.
+ // This should never be directly exposed as its actual location will differ on golem.
+ // See `getRoot` to obtain the actual dependency root.
+ private final Path location;
+
+ public BenchmarkDependency(String directoryName, Path location) {
+ this.directoryName = directoryName;
+ this.location = location;
+ }
+
+ public Path getTarball() {
+ return location.resolve(directoryName + ".tar.gz");
+ }
+
+ public Path getSha1() {
+ return location.resolve(directoryName + ".tar.gz.sha1");
+ }
+
+ public Path getRoot(BenchmarkEnvironment environment) {
+ return environment.translateDependencyPath(directoryName, location);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java
new file mode 100644
index 0000000..aeed6f3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2022, 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.benchmarks;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.rules.TemporaryFolder;
+
+public class BenchmarkEnvironment {
+
+ private final BenchmarkConfig config;
+ private final TemporaryFolder temp;
+ private final boolean isGolem;
+
+ public BenchmarkEnvironment(BenchmarkConfig config, TemporaryFolder temp, boolean isGolem) {
+ this.config = config;
+ this.temp = temp;
+ this.isGolem = isGolem;
+ }
+
+ public BenchmarkConfig getConfig() {
+ return config;
+ }
+
+ public TemporaryFolder getTemp() {
+ return temp;
+ }
+
+ public Path translateDependencyPath(String directoryName, Path location) {
+ return isGolem
+ ? Paths.get("benchmarks", config.getName() + "Group", directoryName)
+ : location.resolve(directoryName);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMainEntryRunner.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMainEntryRunner.java
index 3e5a86a..3151343 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMainEntryRunner.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMainEntryRunner.java
@@ -8,15 +8,21 @@
public class BenchmarkMainEntryRunner {
public static void main(String[] args) throws Exception {
- if (args.length != 2) {
+ if (args.length != 3) {
throw new RuntimeException("Invalid arguments. Expected exactly one benchmark and target");
}
String benchmarkName = args[0];
String targetIdentifier = args[1];
+ String isGolemArg = args[2];
BenchmarkIdentifier identifier = BenchmarkIdentifier.parse(benchmarkName, targetIdentifier);
if (identifier == null) {
throw new RuntimeException("Invalid identifier identifier: " + benchmarkName);
}
+ boolean isGolem = isGolemArg.equals("golem");
+ if (!isGolem && !isGolemArg.equals("local")) {
+ throw new RuntimeException(
+ "Invalid value for arg 3, expected 'golem' or 'local', got '" + isGolemArg + "'");
+ }
BenchmarkCollection collection = BenchmarkCollection.computeCollection();
BenchmarkConfig config = collection.getBenchmark(identifier);
if (config == null) {
@@ -24,7 +30,7 @@
}
TemporaryFolder temp = new TemporaryFolder();
temp.create();
- config.run(temp);
+ config.run(new BenchmarkEnvironment(config, temp, isGolem));
temp.delete();
}
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMethod.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMethod.java
index 8c7e372..ec22276 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMethod.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMethod.java
@@ -3,10 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks;
-import org.junit.rules.TemporaryFolder;
-
@FunctionalInterface
public interface BenchmarkMethod {
- void run(BenchmarkConfig config, TemporaryFolder temp) throws Exception;
+ void run(BenchmarkEnvironment environment) throws Exception;
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java
index 9483499..62bc0ba 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java
@@ -5,7 +5,8 @@
public enum BenchmarkMetric {
RunTimeRaw,
- CodeSize;
+ CodeSize,
+ StartupTime;
public String getDartType() {
return "Metric." + name();
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResults.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
index f436c26..51f9f3a 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
@@ -9,8 +9,8 @@
public class BenchmarkResults {
- private final boolean isWarmupResults;
- private final LongList runtimeRawResults = new LongArrayList();
+ private final BenchmarkMetric runtimeMetric;
+ private final LongList runtimeResults = new LongArrayList();
private final LongList codeSizeResults = new LongArrayList();
public static BenchmarkResults create() {
@@ -22,15 +22,19 @@
}
private BenchmarkResults(boolean isWarmupResults) {
- this.isWarmupResults = isWarmupResults;
+ this.runtimeMetric = isWarmupResults ? BenchmarkMetric.StartupTime : BenchmarkMetric.RunTimeRaw;
+ }
+
+ private boolean isWarmupResults() {
+ return runtimeMetric == BenchmarkMetric.StartupTime;
}
private String getName(BenchmarkConfig config) {
- return isWarmupResults ? config.getWarmupName() : config.getName();
+ return config.getName();
}
- public void addRuntimeRawResult(long result) {
- runtimeRawResults.add(result);
+ public void addRuntimeResult(long result) {
+ runtimeResults.add(result);
}
public void addCodeSizeResult(long result) {
@@ -53,7 +57,7 @@
verifyMetric(
BenchmarkMetric.RunTimeRaw,
config.getMetrics().contains(BenchmarkMetric.RunTimeRaw),
- !runtimeRawResults.isEmpty());
+ !runtimeResults.isEmpty());
verifyMetric(
BenchmarkMetric.CodeSize,
config.getMetrics().contains(BenchmarkMetric.CodeSize),
@@ -61,11 +65,12 @@
}
public static String prettyTime(long nanoTime) {
- return "" + (nanoTime / 1000000) + "ms";
+ return "" + (nanoTime / 1000000) + " ms";
}
- private void printRunTimeRaw(BenchmarkConfig config, long duration) {
- System.out.println(getName(config) + "(RunTimeRaw): " + prettyTime(duration));
+ private void printRunTime(BenchmarkConfig config, long duration) {
+ String metric = runtimeMetric.name();
+ System.out.println(getName(config) + "(" + metric + "): " + prettyTime(duration));
}
private void printCodeSize(BenchmarkConfig config, long bytes) {
@@ -74,15 +79,15 @@
public void printResults(ResultMode mode, BenchmarkConfig config) {
verifyConfigAndResults(config);
- if (config.hasMetric(BenchmarkMetric.RunTimeRaw)) {
- long sum = runtimeRawResults.stream().mapToLong(l -> l).sum();
+ if (config.hasMetric(runtimeMetric)) {
+ long sum = runtimeResults.stream().mapToLong(l -> l).sum();
if (mode == ResultMode.SUM) {
- printRunTimeRaw(config, sum);
+ printRunTime(config, sum);
} else if (mode == ResultMode.AVERAGE) {
- printRunTimeRaw(config, sum / runtimeRawResults.size());
+ printRunTime(config, sum / runtimeResults.size());
}
}
- if (!isWarmupResults && config.hasMetric(BenchmarkMetric.CodeSize)) {
+ if (!isWarmupResults() && config.hasMetric(BenchmarkMetric.CodeSize)) {
long size = codeSizeResults.getLong(0);
for (int i = 1; i < codeSizeResults.size(); i++) {
if (size != codeSizeResults.getLong(i)) {
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkSuite.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkSuite.java
index 1068f72..cecba1d 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkSuite.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkSuite.java
@@ -6,11 +6,7 @@
/** Enumeration of the benchmark suites on Golem. */
public enum BenchmarkSuite {
R8_BENCHMARKS("R8Benchmarks", "suite"),
- D8_BENCHMARKS("D8KeyBenchmarks", "d8KeySuite"),
- D8_INCREMENTAL_BENCHMARKS("D8IncrementalBenchmarks", "incrementalSuite"),
- OPENSOURCE_BENCHMARKS("OpenSourceAppDumps", "dumpsSuite"),
- MEMORY_BENCHMARKS("R8MemoryBenchmarks", "r8MemorySuite"),
- RETRACE_BENCHMARKS("R8RetraceBenchmarks", "r8RetraceSuite");
+ OPENSOURCE_BENCHMARKS("OpenSourceAppDumps", "dumpsSuite");
private final String golemName;
private final String dartName;
diff --git a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java
new file mode 100644
index 0000000..e6d1d00
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java
@@ -0,0 +1,79 @@
+// Copyright (c) 2022, 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.benchmarks.desugaredlib;
+
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.benchmarks.BenchmarkBase;
+import com.android.tools.r8.benchmarks.BenchmarkConfig;
+import com.android.tools.r8.benchmarks.BenchmarkDependency;
+import com.android.tools.r8.benchmarks.BenchmarkEnvironment;
+import com.android.tools.r8.benchmarks.BenchmarkTarget;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class LegacyDesugaredLibraryBenchmark extends BenchmarkBase {
+
+ private static final BenchmarkDependency androidJar = BenchmarkDependency.getAndroidJar30();
+ private static final BenchmarkDependency legacyConf =
+ new BenchmarkDependency("desugar_jdk_libs_legacy", Paths.get("third_party", "openjdk"));
+
+ public LegacyDesugaredLibraryBenchmark(BenchmarkConfig config, TestParameters parameters) {
+ super(config, parameters);
+ }
+
+ @Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ return parametersFromConfigs(configs());
+ }
+
+ public static List<BenchmarkConfig> configs() {
+ return ImmutableList.of(
+ BenchmarkConfig.builder()
+ .setName("LegacyDesugaredLibraryConf")
+ .setTarget(BenchmarkTarget.D8)
+ .setFromRevision(12150)
+ .setMethod(LegacyDesugaredLibraryBenchmark::run)
+ .addDependency(androidJar)
+ .addDependency(legacyConf)
+ .measureRunTime()
+ .build());
+ }
+
+ public static void run(BenchmarkEnvironment environment) throws Exception {
+ runner(environment.getConfig())
+ .setWarmupIterations(1)
+ .setBenchmarkIterations(10)
+ .reportResultSum()
+ .run(
+ results ->
+ testForD8(environment.getTemp(), Backend.DEX)
+ .setMinApi(AndroidApiLevel.B)
+ .addLibraryFiles(androidJar.getRoot(environment).resolve("android.jar"))
+ .apply(
+ b ->
+ b.getBuilder()
+ .addDesugaredLibraryConfiguration(
+ StringResource.fromFile(
+ legacyConf
+ .getRoot(environment)
+ .resolve("desugar_jdk_libs.json"))))
+ .benchmarkCompile(results));
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println(Stream.of("Hello", "world!").collect(Collectors.joining(" ")));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java b/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java
index b91e5b1..a838108 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java
@@ -3,16 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks.helloworld;
-import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.benchmarks.BenchmarkBase;
import com.android.tools.r8.benchmarks.BenchmarkConfig;
+import com.android.tools.r8.benchmarks.BenchmarkDependency;
+import com.android.tools.r8.benchmarks.BenchmarkEnvironment;
import com.android.tools.r8.benchmarks.BenchmarkMethod;
import com.android.tools.r8.benchmarks.BenchmarkTarget;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import org.junit.runner.RunWith;
@@ -41,22 +45,23 @@
}
// Options/parameter setup to define variants of the benchmark above.
+ // Other benchmarks may not need this kind of options. It is just to help create the variants.
private static class Options {
final BenchmarkTarget target;
final Backend backend;
- final boolean includeLibrary;
+ final BenchmarkDependency library;
final AndroidApiLevel minApi = AndroidApiLevel.B;
public Options(BenchmarkTarget target, Backend backend, boolean includeLibrary) {
this.target = target;
this.backend = backend;
- this.includeLibrary = includeLibrary;
+ library = includeLibrary ? BenchmarkDependency.getRuntimeJarJava8() : null;
}
public String getName() {
// The name include each non-target option for the variants to ensure unique benchmarks.
String backendString = backend.isCf() ? "Cf" : "Dex";
- String libraryString = includeLibrary ? "" : "NoLib";
+ String libraryString = library != null ? "" : "NoLib";
return "HelloWorld" + backendString + libraryString;
}
}
@@ -68,65 +73,77 @@
for (boolean includeLibrary : BooleanUtils.values()) {
for (Backend backend : Backend.values()) {
Options options = new Options(target, backend, includeLibrary);
- benchmarks.add(
+ BenchmarkConfig.Builder builder =
BenchmarkConfig.builder()
// The benchmark is required to have a unique combination of name and target.
.setName(options.getName())
.setTarget(target)
// The benchmark is required to have at least one metric.
- .measureRunTimeRaw()
+ .measureRunTime()
.measureCodeSize()
// The benchmark is required to have a runner method which defines the actual
// execution.
.setMethod(method.apply(options))
// The benchmark is required to set a "golem from revision".
// Find this value by looking at the current revision on golem.
- .setFromRevision(11900)
+ .setFromRevision(12150)
// The benchmark can optionally time the warmup. This is not needed to use a warmup
// in the actual run, only to include it as its own benchmark entry on golem.
- .timeWarmupRuns()
- .build());
+ .measureWarmup();
+ // If compiling with a library it needs to be added as a dependency.
+ if (options.library != null) {
+ builder.addDependency(options.library);
+ }
+ benchmarks.add(builder.build());
}
}
}
public static BenchmarkMethod benchmarkD8(Options options) {
- return (config, temp) ->
- runner(config)
+ return environment ->
+ runner(environment.getConfig())
.setWarmupIterations(1)
.setBenchmarkIterations(100)
.reportResultSum()
.run(
results ->
- testForD8(temp, options.backend)
+ testForD8(environment.getTemp(), options.backend)
.setMinApi(options.minApi)
- .applyIf(!options.includeLibrary, TestBuilder::addLibraryFiles)
+ .addLibraryFiles(getLibraryFiles(options, environment))
.addProgramClasses(TestClass.class)
- // Compile and emit RunTimeRaw measure.
+ // Compile and measure the run time.
.benchmarkCompile(results)
// Measure the output size.
.benchmarkCodeSize(results));
}
public static BenchmarkMethod benchmarkR8(Options options) {
- return (config, temp) ->
- runner(config)
+ return environment ->
+ runner(environment.getConfig())
.setWarmupIterations(1)
.setBenchmarkIterations(4)
.reportResultSum()
.run(
results ->
- testForR8(temp, options.backend)
- .applyIf(!options.includeLibrary, b -> b.addLibraryFiles().addDontWarn("*"))
+ testForR8(environment.getTemp(), options.backend)
+ .addLibraryFiles(getLibraryFiles(options, environment))
+ .applyIf(options.library == null, b -> b.addDontWarn("*"))
.setMinApi(options.minApi)
.addProgramClasses(TestClass.class)
.addKeepMainRule(TestClass.class)
- // Compile and emit RunTimeRaw measure.
+ // Compile and measure the run time.
.benchmarkCompile(results)
// Measure the output size.
.benchmarkCodeSize(results));
}
+ private static Collection<Path> getLibraryFiles(
+ Options options, BenchmarkEnvironment environment) {
+ return options.library != null
+ ? Collections.singletonList(options.library.getRoot(environment).resolve("rt.jar"))
+ : Collections.emptyList();
+ }
+
static class TestClass {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/debuginfo/Regress216178582Test.java b/src/test/java/com/android/tools/r8/debuginfo/Regress216178582Test.java
index 3f384d4..ac4be8c 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/Regress216178582Test.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/Regress216178582Test.java
@@ -48,6 +48,7 @@
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(TestClass.class)
.addKeepAttributeLineNumberTable()
+ .addOptionsModification(o -> o.testing.forcePcBasedEncoding = true)
.compile()
.inspect(
inspector -> {
diff --git a/src/test/java/com/android/tools/r8/debuginfo/pc2pc/SharedPc2PcDebugInfo.java b/src/test/java/com/android/tools/r8/debuginfo/pc2pc/SharedPc2PcDebugInfo.java
new file mode 100644
index 0000000..0bbdf46
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debuginfo/pc2pc/SharedPc2PcDebugInfo.java
@@ -0,0 +1,106 @@
+// Copyright (c) 2022, 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.debuginfo.pc2pc;
+
+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.graph.DexDebugInfo;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class SharedPc2PcDebugInfo extends TestBase {
+
+ static final List<String> METHODS = Arrays.asList("m1", "m2", "m3", "m4");
+ static final String EXPECTED = StringUtils.lines(METHODS);
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDefaultDexRuntime().withApiLevel(AndroidApiLevel.B).build();
+ }
+
+ public SharedPc2PcDebugInfo(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(TestClass.class)
+ .addKeepClassAndMembersRules(TestClass.class)
+ .addKeepAttributeLineNumberTable()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED)
+ .inspect(
+ inspector -> {
+ ClassSubject clazz = inspector.clazz(TestClass.class);
+ DexEncodedMethod mainMethod = clazz.mainMethod().getMethod();
+ // The main method debug info is smallest using normal line increments.
+ assertTrue(mainMethod.getCode().asDexCode().getDebugInfo().isEventBasedInfo());
+ // The mX methods can share the pc encoding which is smaller than the sum of the
+ // normal encodings.
+ DexDebugInfo shared = null;
+ for (String name : METHODS) {
+ DexEncodedMethod method = clazz.uniqueMethodWithName(name).getMethod();
+ DexDebugInfo debugInfo = method.getCode().asDexCode().getDebugInfo();
+ assertTrue(debugInfo.isPcBasedInfo());
+ // The DEX parser should allocate the same shared instance to each method.
+ assertTrue(shared == null || debugInfo == shared);
+ shared = debugInfo;
+ }
+ });
+ }
+
+ static class TestClass {
+
+ public static void m1() {
+ System.out.print("m");
+ System.out.println("1");
+ }
+
+ public static void m2() {
+ System.out.print("m");
+ System.out.print("2");
+ System.out.println();
+ }
+
+ public static void m3() {
+ PrintStream out = System.out;
+ out.println("m3");
+ }
+
+ public static void m4() {
+ String m = "m";
+ PrintStream out = System.out;
+ out.print(m);
+ String s = "4";
+ PrintStream out1 = System.out;
+ out1.print(s);
+ PrintStream out2 = System.out;
+ out2.println();
+ }
+
+ public static void main(String[] args) {
+ m1();
+ m2();
+ m3();
+ m4();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
index 6d3a0d3..f79b585 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
@@ -84,6 +84,9 @@
@Test
public void testBufferedReaderD8Cf() throws Exception {
+ Assume.assumeTrue(
+ "The alternative 3 configuration is available only in JDK 11 desugared library.",
+ isJDK11DesugaredLibrary());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
// Use D8 to desugar with Java classfile output.
Path jar =
@@ -140,6 +143,9 @@
@Test
public void testBufferedReaderD8() throws Exception {
Assume.assumeTrue(parameters.getRuntime().isDex());
+ Assume.assumeTrue(
+ "The alternative 3 configuration is available only in JDK 11 desugared library.",
+ isJDK11DesugaredLibrary());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
.addLibraryFiles(getLibraryFile())
@@ -166,6 +172,9 @@
@Test
public void testBufferedReaderR8() throws Exception {
Assume.assumeTrue(parameters.getRuntime().isDex());
+ Assume.assumeTrue(
+ "The alternative 3 configuration is available only in JDK 11 desugared library.",
+ isJDK11DesugaredLibrary());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
.addLibraryFiles(getLibraryFile())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
index d80d01d..6ade9c9 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
@@ -214,6 +214,8 @@
LibraryDesugaringTestConfiguration.builder()
.setMinApi(apiLevel)
// Minimal configuration with a different identifier.
+ // The j$.time is rewritten because empty flags are equivalent to an empty
+ // specification, and no marker is set for empty specifications.
.addDesugaredLibraryConfiguration(
StringResource.fromString(
"{"
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
index 86d87d5..0c4d6f6 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
@@ -26,6 +26,7 @@
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.WorkList;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -139,7 +140,8 @@
false,
minApi.getLevel());
MachineDesugaredLibrarySpecification specification =
- spec.toMachineSpecification(new InternalOptions(factory, new Reporter()), getLibraryFile());
+ spec.toMachineSpecification(
+ new InternalOptions(factory, new Reporter()), getLibraryFile(), Timing.empty());
Set<String> wrappersInSpec =
specification.getWrappers().keySet().stream()
.map(DexType::toString)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
index c21b7ea..3209290 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
@@ -78,6 +78,11 @@
public ObjectsTest(TestParameters parameters, boolean libraryDesugarJavaUtilObjects) {
this.parameters = parameters;
+ if (libraryDesugarJavaUtilObjects) {
+ Assume.assumeTrue(
+ "The alternative 3 configuration is available only in JDK 11 desugared library.",
+ isJDK11DesugaredLibrary());
+ }
this.libraryDesugarJavaUtilObjects = libraryDesugarJavaUtilObjects;
this.androidJar =
ToolHelper.getAndroidJar(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
index e629c47..5d9cf31 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
@@ -26,7 +26,7 @@
private final TestParameters parameters;
private final boolean shrinkDesugaredLibrary;
- @Parameters(name = "machine: {0}, {2}, shrink: {1}")
+ @Parameters(name = "{1}, shrink: {0}")
public static List<Object[]> data() {
return buildParameters(
BooleanUtils.values(),
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java
index 125b4ec..f107b2a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java
@@ -23,6 +23,7 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.util.Map;
import org.junit.Assume;
@@ -46,7 +47,8 @@
public void testMultiLevel() throws IOException {
Assume.assumeTrue(ToolHelper.isLocalDevelopment());
- LegacyToHumanSpecificationConverter converter = new LegacyToHumanSpecificationConverter();
+ LegacyToHumanSpecificationConverter converter =
+ new LegacyToHumanSpecificationConverter(Timing.empty());
InternalOptions options = new InternalOptions();
@@ -57,7 +59,11 @@
StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()));
MultiAPILevelHumanDesugaredLibrarySpecification humanSpec1 =
- converter.convertAllAPILevels(spec, ToolHelper.getAndroidJar(31), options);
+ converter.convertAllAPILevels(
+ spec,
+ ToolHelper.getDesugarJDKLibs(),
+ ToolHelper.getAndroidJar(getRequiredCompilationAPILevel()),
+ options);
Box<String> json = new Box<>();
MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.export(
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java
index 9dcd9cb..c11a623 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/VirtualMethodOverrideEnumUnboxingTest.java
@@ -6,7 +6,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.KeepConstantArguments;
import com.android.tools.r8.NeverClassInline;
@@ -67,8 +67,7 @@
MethodSubject methodOnB =
inspector.clazz(B.class).uniqueMethodWithFinalName(methodOnA.getFinalName());
assertThat(methodOnB, isPresent());
- // TODO(b/171784168): Should be true.
- assertFalse(methodOnB.streamInstructions().anyMatch(x -> x.asDexInstruction().isInvokeSuper()));
+ assertTrue(methodOnB.streamInstructions().anyMatch(x -> x.asDexInstruction().isInvokeSuper()));
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceCheckCastTest.java b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceCheckCastTest.java
new file mode 100644
index 0000000..01f306a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceCheckCastTest.java
@@ -0,0 +1,154 @@
+// Copyright (c) 2022, 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.ir.optimize.interfaces;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoVerticalClassMerging;
+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.Version;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+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;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class OpenInterfaceCheckCastTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForRuntime(parameters)
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ // TODO(b/214496607): I should not be merged into A in the first place, since I is open.
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(true));
+ }
+
+ private List<Class<?>> getProgramClasses() {
+ return ImmutableList.of(I.class, A.class, B.class);
+ }
+
+ private byte[] getTransformedMainClass() throws IOException {
+ return transformer(Main.class)
+ .transformTypeInsnInMethod(
+ "asI",
+ (opcode, type, visitor) -> {
+ assertEquals(opcode, Opcodes.CHECKCAST);
+ assertEquals(type, binaryName(A.class));
+ visitor.visitTypeInsn(opcode, binaryName(I.class));
+ })
+ .transformTypeInsnInMethod(
+ "getB",
+ (opcode, type, visitor) -> {
+ assertEquals(opcode, Opcodes.NEW);
+ assertEquals(type, binaryName(A.class));
+ visitor.visitTypeInsn(opcode, binaryName(B.class));
+ })
+ .transformMethodInsnInMethod(
+ "getB",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ assertEquals(opcode, Opcodes.INVOKESPECIAL);
+ assertEquals(owner, binaryName(A.class));
+ assertEquals(name, "<init>");
+ visitor.visitMethodInsn(opcode, binaryName(B.class), name, descriptor, isInterface);
+ })
+ .transform();
+ }
+
+ private List<String> getExpectedOutputLines(boolean isR8) {
+ if (isR8) {
+ // TODO(b/214496607): R8 should not optimize the check-cast instruction since I is open.
+ return ImmutableList.of("OK", "OK");
+ }
+ if (parameters.isDexRuntime()
+ && parameters
+ .getDexRuntimeVersion()
+ .isEqualToOneOf(Version.V5_1_1, Version.V8_1_0, Version.V9_0_0, Version.DEFAULT)) {
+ return ImmutableList.of("OK", "OK");
+ }
+ return ImmutableList.of("OK", "FAIL");
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ try {
+ asI(getA());
+ System.out.println("OK");
+ } catch (ClassCastException e) {
+ System.out.println("FAIL");
+ }
+ try {
+ asI(getB());
+ System.out.println("OK");
+ } catch (ClassCastException e) {
+ System.out.println("FAIL");
+ }
+ }
+
+ @NeverInline
+ static I asI(I i) {
+ return (A) i; // transformed into a cast to I.
+ }
+
+ static I getA() {
+ return new A();
+ }
+
+ static I getB() {
+ return new A(); // transformed into new B().
+ }
+ }
+
+ @NoVerticalClassMerging
+ interface I {}
+
+ static class A implements I {}
+
+ static class B {}
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceInliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceInliningTest.java
new file mode 100644
index 0000000..98db3cc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceInliningTest.java
@@ -0,0 +1,141 @@
+// Copyright (c) 2022, 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.ir.optimize.interfaces;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NoVerticalClassMerging;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+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;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class OpenInterfaceInliningTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForRuntime(parameters)
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .addKeepClassAndMembersRules(Main.class)
+ // TODO(b/214496607): I should not be merged into A in the first place, since I is open.
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(true));
+ }
+
+ private List<Class<?>> getProgramClasses() {
+ return ImmutableList.of(I.class, A.class, B.class);
+ }
+
+ private byte[] getTransformedMainClass() throws IOException {
+ return transformer(Main.class)
+ .transformTypeInsnInMethod(
+ "getB",
+ (opcode, type, visitor) -> {
+ assertEquals(opcode, Opcodes.NEW);
+ assertEquals(type, binaryName(A.class));
+ visitor.visitTypeInsn(opcode, binaryName(B.class));
+ })
+ .transformMethodInsnInMethod(
+ "getB",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ assertEquals(opcode, Opcodes.INVOKESPECIAL);
+ assertEquals(owner, binaryName(A.class));
+ assertEquals(name, "<init>");
+ visitor.visitMethodInsn(opcode, binaryName(B.class), name, descriptor, isInterface);
+ })
+ .transform();
+ }
+
+ private List<String> getExpectedOutputLines(boolean isR8) {
+ if (isR8) {
+ // TODO(b/214496607): R8 should not inline the invoke instruction since I is open.
+ return ImmutableList.of("A", "A");
+ }
+ return ImmutableList.of("A", "ICCE");
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ getA().m();
+ try {
+ getB().m();
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("ICCE");
+ }
+ }
+
+ static I getA() {
+ return new A();
+ }
+
+ static I getB() {
+ return new A(); // transformed into new B().
+ }
+ }
+
+ @NoVerticalClassMerging
+ interface I {
+
+ void m();
+ }
+
+ static class A implements I {
+
+ @Override
+ public void m() {
+ System.out.println("A");
+ }
+ }
+
+ static class B {
+
+ public void m() {
+ System.out.println("B");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceInstanceofTest.java b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceInstanceofTest.java
new file mode 100644
index 0000000..d73550c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenInterfaceInstanceofTest.java
@@ -0,0 +1,137 @@
+// Copyright (c) 2022, 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.ir.optimize.interfaces;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoVerticalClassMerging;
+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.Version;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+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;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class OpenInterfaceInstanceofTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForRuntime(parameters)
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ // TODO(b/214496607): I should not be merged into A in the first place, since I is open.
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(true));
+ }
+
+ private List<Class<?>> getProgramClasses() {
+ return ImmutableList.of(I.class, A.class, B.class);
+ }
+
+ private byte[] getTransformedMainClass() throws IOException {
+ return transformer(Main.class)
+ .transformTypeInsnInMethod(
+ "getB",
+ (opcode, type, visitor) -> {
+ assertEquals(opcode, Opcodes.NEW);
+ assertEquals(type, binaryName(A.class));
+ visitor.visitTypeInsn(opcode, binaryName(B.class));
+ })
+ .transformMethodInsnInMethod(
+ "getB",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ assertEquals(opcode, Opcodes.INVOKESPECIAL);
+ assertEquals(owner, binaryName(A.class));
+ assertEquals(name, "<init>");
+ visitor.visitMethodInsn(opcode, binaryName(B.class), name, descriptor, isInterface);
+ })
+ .transform();
+ }
+
+ private List<String> getExpectedOutputLines(boolean isR8) {
+ if (isR8) {
+ // TODO(b/214496607): R8 should not optimize the instanceof instruction since I is open.
+ return ImmutableList.of("true", "true");
+ }
+ if (parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isEqualTo(Version.V7_0_0)) {
+ return ImmutableList.of("true", "true");
+ }
+ return ImmutableList.of("true", "false");
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ System.out.println(isIOrNull(getA()));
+ System.out.println(isIOrNull(getB()));
+ }
+
+ @NeverInline
+ static boolean isIOrNull(I i) {
+ if (i != null) {
+ return i instanceof I;
+ }
+ return true;
+ }
+
+ static I getA() {
+ return new A();
+ }
+
+ static I getB() {
+ return new A(); // transformed into new B().
+ }
+ }
+
+ @NoVerticalClassMerging
+ interface I {}
+
+ static class A implements I {}
+
+ static class B {}
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java
new file mode 100644
index 0000000..7740192
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/interfaces/OpenUninstantiatedInterfaceInstanceofTest.java
@@ -0,0 +1,127 @@
+// Copyright (c) 2022, 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.ir.optimize.interfaces;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NeverInline;
+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.Version;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+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;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class OpenUninstantiatedInterfaceInstanceofTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForRuntime(parameters)
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(false));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getTransformedMainClass())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(getExpectedOutputLines(true));
+ }
+
+ private List<Class<?>> getProgramClasses() {
+ return ImmutableList.of(I.class, A.class, B.class);
+ }
+
+ private byte[] getTransformedMainClass() throws IOException {
+ return transformer(Main.class)
+ .transformTypeInsnInMethod(
+ "getB",
+ (opcode, type, visitor) -> {
+ assertEquals(opcode, Opcodes.NEW);
+ assertEquals(type, binaryName(A.class));
+ visitor.visitTypeInsn(opcode, binaryName(B.class));
+ })
+ .transformMethodInsnInMethod(
+ "getB",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ assertEquals(opcode, Opcodes.INVOKESPECIAL);
+ assertEquals(owner, binaryName(A.class));
+ assertEquals(name, "<init>");
+ visitor.visitMethodInsn(opcode, binaryName(B.class), name, descriptor, isInterface);
+ })
+ .transform();
+ }
+
+ private List<String> getExpectedOutputLines(boolean isR8) {
+ if (isR8) {
+ // TODO(b/214496607): R8 should not optimize the instanceof instruction since I is open.
+ return ImmutableList.of("true");
+ }
+ if (parameters.isDexRuntime()) {
+ if (parameters.getDexRuntimeVersion().isEqualTo(Version.V7_0_0)
+ || parameters.getDexRuntimeVersion().isEqualTo(Version.V13_MASTER)) {
+ return ImmutableList.of("true");
+ }
+ }
+ return ImmutableList.of("false");
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ I b = getB();
+ if (b != null) {
+ System.out.println(b instanceof I);
+ }
+ }
+
+ @NeverInline
+ static I getB() {
+ return new A(); // transformed into new B().
+ }
+ }
+
+ interface I {}
+
+ static class A implements I {}
+
+ static class B {}
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java b/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java
new file mode 100644
index 0000000..dc3ca19
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java
@@ -0,0 +1,113 @@
+// Copyright (c) 2021, 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.ir.optimize.loops;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class LoopWith1Iterations extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public LoopWith1Iterations(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testLoopRemoved() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(Main.class)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .noMinification()
+ .compile()
+ .inspect(this::assertLoopRemoved)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ "object",
+ "loop1fori",
+ "object",
+ "loop1for",
+ "object",
+ "loop1foriAbstractValue",
+ "object",
+ "loop1forAbstractValue");
+ }
+
+ private void assertLoopRemoved(CodeInspector inspector) {
+ inspector
+ .clazz(Main.class)
+ .allMethods()
+ .forEach(
+ m ->
+ org.junit.Assert.assertTrue(
+ m.streamInstructions()
+ .noneMatch(i -> i.isArrayLength() || i.isGoto() || i.isIf())));
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ loop1fori();
+ loop1for();
+ loop1foriAbstractValue();
+ loop1forAbstractValue();
+ }
+
+ @NeverInline
+ public static void loop1fori() {
+ Object[] objects = new Object[1];
+ for (int i = 0; i < objects.length; i++) {
+ System.out.println("object");
+ }
+ System.out.println("loop1fori");
+ }
+
+ @NeverInline
+ public static void loop1for() {
+ Object[] objects = new Object[1];
+ for (Object object : objects) {
+ System.out.println("object");
+ }
+ System.out.println("loop1for");
+ }
+
+ @NeverInline
+ public static Object[] getObjectArray1() {
+ return new Object[1];
+ }
+
+ @NeverInline
+ public static void loop1foriAbstractValue() {
+ Object[] objects = getObjectArray1();
+ for (int i = 0; i < objects.length; i++) {
+ System.out.println("object");
+ }
+ System.out.println("loop1foriAbstractValue");
+ }
+
+ @NeverInline
+ public static void loop1forAbstractValue() {
+ Object[] objects = getObjectArray1();
+ for (Object object : objects) {
+ System.out.println("object");
+ }
+ System.out.println("loop1forAbstractValue");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
index 0e4a3a2..65132d2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/UninstantiatedAnnotatedArgumentsTest.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.KeepUnusedArguments;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoParameterReordering;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.errors.Unreachable;
@@ -68,6 +69,7 @@
.enableNeverClassInliningAnnotations()
.enableConstantArgumentAnnotations(keepUninstantiatedArguments)
.enableInliningAnnotations()
+ .enableNoParameterReorderingAnnotations()
.enableUnusedArgumentAnnotations()
// TODO(b/123060011): Mapping not working in presence of argument removal.
.minification(keepUninstantiatedArguments)
@@ -168,6 +170,7 @@
@KeepConstantArguments
@KeepUnusedArguments
@NeverInline
+ @NoParameterReordering
static void testRemoveStaticFromStart(
@Uninstantiated Dead uninstantiated,
@Instantiated String instantiated,
@@ -178,6 +181,7 @@
@KeepConstantArguments
@KeepUnusedArguments
@NeverInline
+ @NoParameterReordering
static void testRemoveStaticFromMiddle(
@Instantiated String instantiated,
@Uninstantiated Dead uninstantiated,
@@ -188,6 +192,7 @@
@KeepConstantArguments
@KeepUnusedArguments
@NeverInline
+ @NoParameterReordering
static void testRemoveStaticFromEnd(
@Instantiated String instantiated,
@Instantiated String otherInstantiated,
@@ -198,6 +203,7 @@
@KeepConstantArguments
@KeepUnusedArguments
@NeverInline
+ @NoParameterReordering
void testRemoveVirtualFromStart(
@Uninstantiated Dead uninstantiated,
@Instantiated String instantiated,
@@ -208,6 +214,7 @@
@KeepConstantArguments
@KeepUnusedArguments
@NeverInline
+ @NoParameterReordering
void testRemoveVirtualFromMiddle(
@Instantiated String instantiated,
@Uninstantiated Dead uninstantiated,
@@ -218,6 +225,7 @@
@KeepConstantArguments
@KeepUnusedArguments
@NeverInline
+ @NoParameterReordering
void testRemoveVirtualFromEnd(
@Instantiated String instantiated,
@Instantiated String otherInstantiated,
diff --git a/src/test/java/com/android/tools/r8/jasmin/Regress65007724.java b/src/test/java/com/android/tools/r8/jasmin/Regress65007724.java
index 1eb0586..cdc5b63 100644
--- a/src/test/java/com/android/tools/r8/jasmin/Regress65007724.java
+++ b/src/test/java/com/android/tools/r8/jasmin/Regress65007724.java
@@ -3,11 +3,29 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.jasmin;
-import static org.junit.Assert.assertEquals;
-
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class Regress65007724 extends JasminTestBase {
+
+ private final TestParameters parameters;
+
+ public Regress65007724(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
@Test
public void testThat16BitsIndexAreAllowed() throws Exception {
JasminBuilder builder = new JasminBuilder();
@@ -28,8 +46,16 @@
"invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
"return");
- String expected = runOnJava(builder, clazz.name);
- String artResult = runOnArtD8(builder, clazz.name);
- assertEquals(expected, artResult);
+ D8TestRunResult d8TestRunResult =
+ testForD8(parameters.getBackend())
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClassFileData(builder.buildClasses())
+ .run(parameters.getRuntime(), clazz.name);
+ if (parameters.getDexRuntimeVersion().isEqualTo(Version.V13_MASTER)) {
+ // See b/220821265
+ d8TestRunResult.assertFailure();
+ } else {
+ d8TestRunResult.assertSuccessWithOutput("Hello World!");
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/StaticFieldClassInitMemberRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/StaticFieldClassInitMemberRebindingTest.java
new file mode 100644
index 0000000..c31c93d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/memberrebinding/StaticFieldClassInitMemberRebindingTest.java
@@ -0,0 +1,105 @@
+// Copyright (c) 2022, 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.memberrebinding;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+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 StaticFieldClassInitMemberRebindingTest extends TestBase {
+
+ private static final String EXPECTED = "World!";
+ private static final String R8_EXPECTED = "Hello World!";
+
+ private final String NEW_A_DESCRIPTOR = "Lfoo/A;";
+ private final String NEW_B_DESCRIPTOR = "Lfoo/B;";
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
+ .addProgramClassFileData(
+ getMainWithRewrittenDescriptors(), getAWithPackageFoo(), getBWithRewrittenDescriptors())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(
+ getMainWithRewrittenDescriptors(), getAWithPackageFoo(), getBWithRewrittenDescriptors())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .addOptionsModification(options -> options.enableVisibilityBridgeRemoval = false)
+ .run(parameters.getRuntime(), Main.class)
+ // TODO(b/220668540): R8 should not change class loading semantics.
+ .assertSuccessWithOutputLines(R8_EXPECTED);
+ }
+
+ private byte[] getAWithPackageFoo() throws Exception {
+ return transformer(A.class).setClassDescriptor(NEW_A_DESCRIPTOR).transform();
+ }
+
+ private byte[] getBWithRewrittenDescriptors() throws Exception {
+ return transformer(B.class)
+ .setClassDescriptor(NEW_B_DESCRIPTOR)
+ .setSuper(NEW_A_DESCRIPTOR)
+ .replaceClassDescriptorInMethodInstructions(descriptor(A.class), NEW_A_DESCRIPTOR)
+ .transform();
+ }
+
+ private byte[] getMainWithRewrittenDescriptors() throws Exception {
+ return transformer(Main.class)
+ .replaceClassDescriptorInMethodInstructions(descriptor(B.class), NEW_B_DESCRIPTOR)
+ .transform();
+ }
+
+ static class /* foo. */ A {
+
+ @NeverInline
+ public static void foo() {
+ System.out.println("World!");
+ }
+ }
+
+ public static class /* foo */ B extends A {
+
+ static {
+ System.out.print("Hello ");
+ }
+ }
+
+ public static class Main {
+
+ @NeverInline
+ public static void test() {
+ B.foo(); // Resolves to A.foo(), hence does not trigger B.<clinit>().
+ }
+
+ public static void main(String[] args) {
+ test();
+ if (System.currentTimeMillis() == 0) {
+ // Needed to ensure we do not remove B.<clinit>() in first round of treeshaking before
+ // running member rebinding analysis.
+ new B();
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithInstanceInitializerCollisionTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithInstanceInitializerCollisionTest.java
index 66a4cdc..838e914 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithInstanceInitializerCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithInstanceInitializerCollisionTest.java
@@ -36,8 +36,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptMethodTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptMethodTest.java
index 70dbf9d..5f30d86 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptMethodTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptMethodTest.java
@@ -38,8 +38,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addKeepRules("-keep class " + Main.class.getTypeName() + " { void foo(...); }")
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
// TODO(b/173398086): uniqueMethodWithName() does not work with proto changes.
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptVirtualMethodTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptVirtualMethodTest.java
index e9655ba..3b8abab 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptVirtualMethodTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithKeptVirtualMethodTest.java
@@ -39,8 +39,6 @@
.addInnerClasses(getClass())
.addKeepClassAndMembersRules(Main.class)
.addKeepRules("-keepclassmembers class " + A.class.getTypeName() + " { void foo(...); }")
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithLibraryOverrideTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithLibraryOverrideTest.java
index 52d4df1..31a766e 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithLibraryOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithLibraryOverrideTest.java
@@ -38,8 +38,6 @@
.addLibraryClasses(A.class, B.class, Library.class)
.addDefaultRuntimeLibrary(parameters)
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableInliningAnnotations()
// TODO(b/173398086): uniqueMethodWithName() does not work with proto changes.
.noMinification()
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithParameterAnnotationsTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithParameterAnnotationsTest.java
index a9b9af9..37bfc73 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithParameterAnnotationsTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithParameterAnnotationsTest.java
@@ -44,8 +44,6 @@
.addKeepMainRule(Main.class)
.addKeepClassAndMembersRules(Foo.class, Bar.class)
.addKeepRuntimeVisibleAnnotations()
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
// TODO(b/173398086): uniqueMethodWithName() does not work with proto changes.
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithVirtualMethodCollisionTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithVirtualMethodCollisionTest.java
index babbf9f..0e63441 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithVirtualMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithVirtualMethodCollisionTest.java
@@ -38,8 +38,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
// TODO(b/173398086): uniqueMethodWithName() does not work with proto changes.
diff --git a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithoutSharingTest.java b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithoutSharingTest.java
index d9190df..dcde130 100644
--- a/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithoutSharingTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/proto/ProtoNormalizationWithoutSharingTest.java
@@ -37,8 +37,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options -> options.testing.enableExperimentalProtoNormalization = true)
.enableInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java b/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java
index 5405ecb..00d373c 100644
--- a/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java
+++ b/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java
@@ -4,13 +4,14 @@
package com.android.tools.r8.regress.b150400371;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-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.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableSet;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.junit.Test;
@@ -45,9 +46,10 @@
MethodSubject main =
inspector.method(InlineInto.class.getDeclaredMethod("main", String[].class));
if (parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport())) {
- // Method has 14 actual lines, the PC mapping table will have about 50.
+ // Method has 2 actual lines for inlining of foo.
+ // The pc2pc encoding is larger than normal encoding, so it is just the two lines.
IntSet lines = new IntArraySet(main.getLineNumberTable().getLines());
- assertTrue(lines.size() > 20);
+ assertEquals(ImmutableSet.of(1, 2), lines);
} else {
assertNull(main.getLineNumberTable());
}
diff --git a/src/test/java/com/android/tools/r8/shaking/RemoveCallToStaticInitTest.java b/src/test/java/com/android/tools/r8/shaking/RemoveCallToStaticInitTest.java
new file mode 100644
index 0000000..0d1fb3d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/RemoveCallToStaticInitTest.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2022, 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.shaking;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+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 RemoveCallToStaticInitTest extends TestBase {
+
+ private static final String EXPECTED = "Hello World!";
+ private static final String R8_EXPECTED = "World!";
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
+ .addProgramClasses(A.class, Main.class)
+ .addProgramClassFileData(getBWithBridge())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(A.class, Main.class)
+ .addProgramClassFileData(getBWithBridge())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .run(parameters.getRuntime(), Main.class)
+ // TODO(b/220667525): R8 should emit EXPECTED
+ .assertSuccessWithOutputLines(R8_EXPECTED)
+ .inspect(
+ inspector -> {
+ ClassSubject clazz = inspector.clazz(B.class);
+ assertThat(clazz, isPresent());
+ // TODO(b/220667525): Should not remove bridge due to class init.
+ assertThat(clazz.uniqueMethodWithName("foo"), not(isPresent()));
+ });
+ }
+
+ private byte[] getBWithBridge() throws Exception {
+ return transformer(B.class)
+ .setAccessFlags(B.class.getMethod("foo"), MethodAccessFlags::setBridge)
+ .transform();
+ }
+
+ public static class A {
+
+ @NeverInline
+ public static void foo() {
+ System.out.println("World!");
+ }
+ }
+
+ public static class B extends A {
+
+ static {
+ System.out.print("Hello ");
+ }
+
+ @NeverInline
+ public static /* bridge */ void foo() {
+ A.foo();
+ }
+ }
+
+ public static class Main {
+
+ @NeverInline
+ public static void test() {
+ B.foo();
+ }
+
+ public static void main(String[] args) {
+ test();
+ }
+ }
+}
diff --git a/third_party/openjdk/desugar_jdk_libs_legacy.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_legacy.tar.gz.sha1
new file mode 100644
index 0000000..bcf1956
--- /dev/null
+++ b/third_party/openjdk/desugar_jdk_libs_legacy.tar.gz.sha1
@@ -0,0 +1 @@
+5e0a4ead7e29d87c31f0facb2e7971caff7ac443
\ No newline at end of file
diff --git a/tools/adb.py b/tools/adb.py
index 07ca034..2e015a0 100644
--- a/tools/adb.py
+++ b/tools/adb.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2020, 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.
diff --git a/tools/api_sample_coverage.py b/tools/api_sample_coverage.py
index 4eea8c7..2d9b0d2 100755
--- a/tools/api_sample_coverage.py
+++ b/tools/api_sample_coverage.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/apk_masseur.py b/tools/apk_masseur.py
index b1ea43e..b363bb7 100755
--- a/tools/apk_masseur.py
+++ b/tools/apk_masseur.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/archive.py b/tools/archive.py
index 24e8e0a..d3aa196 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
@@ -37,7 +37,7 @@
# TODO(mkroghj) This would not work for r8-lib, maybe use utils.getR8Version.
output = subprocess.check_output([
jdk.GetJavaExecutable(), '-jar', jar_path, '--version'
- ])
+ ]).decode('utf-8')
return output.splitlines()[0].strip()
def GetVersion():
@@ -54,11 +54,11 @@
return subprocess.check_output(['git', 'show', '-s', '--pretty=%d', 'HEAD'])
def GetGitHash():
- return subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
+ return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('utf-8').strip()
def IsMain(version):
branches = subprocess.check_output(['git', 'branch', '-r', '--contains',
- 'HEAD'])
+ 'HEAD']).decode('utf-8')
# CL runs from gerrit does not have a branch, we always treat them as main
# commits to archive these to the hash based location
if len(branches) == 0:
diff --git a/tools/archive_desugar_jdk_libs.py b/tools/archive_desugar_jdk_libs.py
index 91ad6b5..3a9cfd6 100755
--- a/tools/archive_desugar_jdk_libs.py
+++ b/tools/archive_desugar_jdk_libs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
@@ -106,6 +106,8 @@
bazel,
'--bazelrc=/dev/null',
'build',
+ '--sandbox_debug',
+ '--verbose_failures',
'maven_release' + ('_jdk11' if variant == 'jdk11' else '')]
utils.PrintCmd(cmd)
subprocess.check_call(cmd, env=GetJavaEnv())
diff --git a/tools/as_utils.py b/tools/as_utils.py
index 4087137..3c69d10 100644
--- a/tools/as_utils.py
+++ b/tools/as_utils.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/asmifier.py b/tools/asmifier.py
index 3fec231..1a8e4ac 100755
--- a/tools/asmifier.py
+++ b/tools/asmifier.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/benchmarks/get_deps.py b/tools/benchmarks/get_deps.py
index cd28efe..716db48 100644
--- a/tools/benchmarks/get_deps.py
+++ b/tools/benchmarks/get_deps.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/tools/build_aosp.py b/tools/build_aosp.py
index b62ec02..5475830 100755
--- a/tools/build_aosp.py
+++ b/tools/build_aosp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/build_r8lib.py b/tools/build_r8lib.py
index 980715e..8dc0cb8 100755
--- a/tools/build_r8lib.py
+++ b/tools/build_r8lib.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/build_sample_apk.py b/tools/build_sample_apk.py
index 376c5c0..67ead8c 100755
--- a/tools/build_sample_apk.py
+++ b/tools/build_sample_apk.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/checkout_aosp.py b/tools/checkout_aosp.py
index 268b1b3..36a5333 100755
--- a/tools/checkout_aosp.py
+++ b/tools/checkout_aosp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/compare_apk_sizes.py b/tools/compare_apk_sizes.py
index 9a56187..895633e 100755
--- a/tools/compare_apk_sizes.py
+++ b/tools/compare_apk_sizes.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/compare_cts_results.py b/tools/compare_cts_results.py
index 00901ec..0da116d 100755
--- a/tools/compare_cts_results.py
+++ b/tools/compare_cts_results.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/compatdx.py b/tools/compatdx.py
index c4cb320..d58b907 100755
--- a/tools/compatdx.py
+++ b/tools/compatdx.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/compatproguard.py b/tools/compatproguard.py
index 10542e3..7c56549 100755
--- a/tools/compatproguard.py
+++ b/tools/compatproguard.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/compiledump.py b/tools/compiledump.py
index a810cdc..a7809ac 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2020, 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.
diff --git a/tools/create_art_tests.py b/tools/create_art_tests.py
index a64fe71..0c59ae9 100755
--- a/tools/create_art_tests.py
+++ b/tools/create_art_tests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/create_dx_replay.py b/tools/create_dx_replay.py
index cb27a30..8dfb0a0 100755
--- a/tools/create_dx_replay.py
+++ b/tools/create_dx_replay.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
@@ -81,7 +81,7 @@
# create the first lines of the replay script
replay_script = \
-"""#!/usr/bin/env python
+"""#!/usr/bin/env python3
import os
import shutil
import subprocess
diff --git a/tools/create_maven_release.py b/tools/create_maven_release.py
index 01aebe6..b233257 100755
--- a/tools/create_maven_release.py
+++ b/tools/create_maven_release.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
@@ -230,7 +230,7 @@
dependency_lines = []
collect = False
for line in dependencies.splitlines():
- if 'runtimeClasspath' in line and "'main'" in line:
+ if line and 'runtimeClasspath' in line and "'main'" in line:
collect = True
continue
if collect:
diff --git a/tools/d8.py b/tools/d8.py
index 833f7f5..766e690 100755
--- a/tools/d8.py
+++ b/tools/d8.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/d8logger.py b/tools/d8logger.py
index 9fb3508..b523294 100755
--- a/tools/d8logger.py
+++ b/tools/d8logger.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/dex2oat.py b/tools/dex2oat.py
index e21dc7d..7c5a31e 100755
--- a/tools/dex2oat.py
+++ b/tools/dex2oat.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/dexfilemerger.py b/tools/dexfilemerger.py
index 7bdfc22..de4e6ae 100755
--- a/tools/dexfilemerger.py
+++ b/tools/dexfilemerger.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/dexsegments.py b/tools/dexsegments.py
index f984063..7b901de 100755
--- a/tools/dexsegments.py
+++ b/tools/dexsegments.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/dexsplitter.py b/tools/dexsplitter.py
index 415b149..a97d089 100755
--- a/tools/dexsplitter.py
+++ b/tools/dexsplitter.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/disasm.py b/tools/disasm.py
index 368a78f..e37ac4c 100755
--- a/tools/disasm.py
+++ b/tools/disasm.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/download_all_benchmark_dependencies.py b/tools/download_all_benchmark_dependencies.py
index ab29ebd..ed940a3 100755
--- a/tools/download_all_benchmark_dependencies.py
+++ b/tools/download_all_benchmark_dependencies.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/download_kotlin_dev.py b/tools/download_kotlin_dev.py
index 6360cd2..5d2696a 100755
--- a/tools/download_kotlin_dev.py
+++ b/tools/download_kotlin_dev.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2021, 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.
diff --git a/tools/emulator_aosp.py b/tools/emulator_aosp.py
index f63c673..d5f80dc 100755
--- a/tools/emulator_aosp.py
+++ b/tools/emulator_aosp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/extractmarker.py b/tools/extractmarker.py
index 36a9c88..b50a2fd 100755
--- a/tools/extractmarker.py
+++ b/tools/extractmarker.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/find_haning_test.py b/tools/find_haning_test.py
index 29e78aa..786fbcf 100755
--- a/tools/find_haning_test.py
+++ b/tools/find_haning_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/git_sync_cl_chain.py b/tools/git_sync_cl_chain.py
index 09da33e..7dc512e 100755
--- a/tools/git_sync_cl_chain.py
+++ b/tools/git_sync_cl_chain.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/git_utils.py b/tools/git_utils.py
index 9d9c6bd..1e3e7c5 100644
--- a/tools/git_utils.py
+++ b/tools/git_utils.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/golem.py b/tools/golem.py
index eb9bbee..6a4e399 100755
--- a/tools/golem.py
+++ b/tools/golem.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/golem_build.py b/tools/golem_build.py
index c691293..4f668d6 100755
--- a/tools/golem_build.py
+++ b/tools/golem_build.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
@@ -8,26 +8,16 @@
import sys
import gradle
-import retrace_benchmark
import run_benchmark
import run_on_app_dump
GRADLE_ARGS = ['--no-daemon', '-Pno_internal']
-LEGACY_BUILD_TARGETS = [
- 'R8',
- 'D8',
- 'buildExampleJars',
- 'downloadAndroidCts',
- 'downloadDx']
-
def lower(items):
return [ item.lower() for item in items ]
def Main():
targets = set()
- targets.update(lower(LEGACY_BUILD_TARGETS))
- targets.update(lower(retrace_benchmark.GOLEM_BUILD_TARGETS))
targets.update(lower(run_benchmark.GOLEM_BUILD_TARGETS))
targets.update(lower(run_on_app_dump.GOLEM_BUILD_TARGETS))
cmd = GRADLE_ARGS + [target for target in targets]
diff --git a/tools/gradle.py b/tools/gradle.py
index 63c92b5..19fa773 100755
--- a/tools/gradle.py
+++ b/tools/gradle.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
@@ -96,7 +96,7 @@
cmd.extend(args)
utils.PrintCmd(cmd)
with utils.ChangedWorkingDirectory(cwd):
- return subprocess.check_output(cmd, env=GetJavaEnv(env))
+ return subprocess.check_output(cmd, env=GetJavaEnv(env)).decode('utf-8')
def RunGradleWrapperInGetOutput(args, cwd, env=None):
return RunGradleInGetOutput('./gradlew', args, cwd, env=env)
diff --git a/tools/historic_memory_usage.py b/tools/historic_memory_usage.py
index bb08a2e..3ef2268 100755
--- a/tools/historic_memory_usage.py
+++ b/tools/historic_memory_usage.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/historic_run.py b/tools/historic_run.py
index b0f181f..eaaadd5 100755
--- a/tools/historic_run.py
+++ b/tools/historic_run.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/inspect.py b/tools/inspect.py
index 6d655da..80c1ecd 100755
--- a/tools/inspect.py
+++ b/tools/inspect.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/internal_test.py b/tools/internal_test.py
index dae6247..0d591ad 100755
--- a/tools/internal_test.py
+++ b/tools/internal_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
@@ -166,7 +166,7 @@
def ensure_git_clean():
# Ensure clean git repo.
- diff = subprocess.check_output(['git', 'diff'])
+ diff = subprocess.check_output(['git', 'diff']).decode('utf-8')
if len(diff) > 0:
log('Local modifications to the git repo, exiting')
sys.exit(1)
@@ -328,13 +328,13 @@
if archive:
archive_log(stdout, stderr, exitcode, timed_out, cmd)
else:
- print 'Execution of %s resulted in:' % cmd
- print 'exit code: %s ' % exitcode
- print 'timeout: %s ' % timed_out
+ print('Execution of %s resulted in:' % cmd)
+ print('exit code: %s ' % exitcode)
+ print('timeout: %s ' % timed_out)
with open(stderr, 'r') as f:
- print 'stderr: %s' % f.read()
+ print('stderr: %s' % f.read())
with open(stdout, 'r') as f:
- print 'stdout: %s' % f.read()
+ print('stdout: %s' % f.read())
def execute(cmd, archive, env=None):
if cmd == []:
diff --git a/tools/jardiff.py b/tools/jardiff.py
index 894131c..18587ab 100755
--- a/tools/jardiff.py
+++ b/tools/jardiff.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/java.py b/tools/java.py
index 3abfcdd..fb0ef13 100755
--- a/tools/java.py
+++ b/tools/java.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/javac.py b/tools/javac.py
index 0d8ac05..242fac0 100755
--- a/tools/javac.py
+++ b/tools/javac.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/jdk.py b/tools/jdk.py
index b3af7a6..23cacc8 100755
--- a/tools/jdk.py
+++ b/tools/jdk.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/keeprule_benchmark.py b/tools/keeprule_benchmark.py
index 0a7e063..4b843c6 100755
--- a/tools/keeprule_benchmark.py
+++ b/tools/keeprule_benchmark.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2020, 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.
diff --git a/tools/maindex.py b/tools/maindex.py
index ff5329a..735ced5 100755
--- a/tools/maindex.py
+++ b/tools/maindex.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/maven_mirror.py b/tools/maven_mirror.py
index 43ca31e..8a7f4aa 100755
--- a/tools/maven_mirror.py
+++ b/tools/maven_mirror.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/minify_tool.py b/tools/minify_tool.py
index a512665..cef72e5 100755
--- a/tools/minify_tool.py
+++ b/tools/minify_tool.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/notify.py b/tools/notify.py
index b195357..34676ba 100644
--- a/tools/notify.py
+++ b/tools/notify.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/performance_try.py b/tools/performance_try.py
index 5830cea..0c09e70 100755
--- a/tools/performance_try.py
+++ b/tools/performance_try.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/printseeds.py b/tools/printseeds.py
index 4f389d5..6c0ee8c 100755
--- a/tools/printseeds.py
+++ b/tools/printseeds.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/printuses.py b/tools/printuses.py
index 17d3df1..5253796 100755
--- a/tools/printuses.py
+++ b/tools/printuses.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/proguard.py b/tools/proguard.py
index 5984622..4a3ae7d 100755
--- a/tools/proguard.py
+++ b/tools/proguard.py
@@ -1,16 +1,13 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
# Run ProGuard, Google's internal version
-from __future__ import print_function
-
import os
import subprocess
import sys
-from exceptions import ValueError
import jdk
import utils
diff --git a/tools/r8.py b/tools/r8.py
index 60c60a0..31abcf6 100755
--- a/tools/r8.py
+++ b/tools/r8.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/r8bisect.py b/tools/r8bisect.py
index 74c880e..1b35eb3 100755
--- a/tools/r8bisect.py
+++ b/tools/r8bisect.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/retrace_benchmark.py b/tools/retrace_benchmark.py
deleted file mode 100755
index 42ed792..0000000
--- a/tools/retrace_benchmark.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-import argparse
-import os
-import subprocess
-import sys
-import time
-
-import golem
-import jdk
-import proguard
-import utils
-
-GOLEM_BUILD_TARGETS = ['R8Lib']
-RETRACERS = ['r8', 'proguard', 'remapper']
-
-def parse_arguments(argv):
- parser = argparse.ArgumentParser(
- description = 'Run r8 retrace bootstrap benchmarks.')
- parser.add_argument('--golem',
- help = 'Link in third party dependencies.',
- default = False,
- action = 'store_true')
- parser.add_argument('--ignore-java-version',
- help='Do not check java version',
- default=False,
- action='store_true')
- parser.add_argument('--print-runtimeraw',
- metavar='BENCHMARKNAME',
- help='Print the line \'<BENCHMARKNAME>(RunTimeRaw):' +
- ' <elapsed> ms\' at the end where <elapsed> is' +
- ' the elapsed time in milliseconds.')
- parser.add_argument('--retracer',
- help='The retracer to use',
- choices=RETRACERS,
- required=True)
- parser.add_argument('--download-benchmarks',
- help='Download retrace benchmarks',
- default=False,
- action='store_true')
- options = parser.parse_args(argv)
- return options
-
-def download_benchmarks():
- utils.DownloadFromGoogleCloudStorage(
- os.path.join(utils.THIRD_PARTY, 'retrace_benchmark') + '.tar.gz.sha1')
-
-def run_retrace(options, temp):
- if options.download_benchmarks:
- download_benchmarks()
- if options.retracer == 'r8':
- retracer_args = [
- '-cp', utils.R8LIB_JAR, 'com.android.tools.r8.retrace.Retrace']
- elif options.retracer == 'proguard':
- retracer_args = ['-jar', proguard.getRetraceJar()]
- elif options.retracer == 'remapper':
- retracer_args = ['-jar',
- os.path.join(
- utils.THIRD_PARTY,
- 'remapper',
- 'remapper_deploy.jar')]
- else:
- assert False, "Unexpected retracer " + options.retracer
- retrace_args = [jdk.GetJavaExecutable()] + retracer_args + [
- os.path.join(utils.THIRD_PARTY, 'retrace_benchmark', 'r8lib.jar.map'),
- os.path.join(utils.THIRD_PARTY, 'retrace_benchmark', 'stacktrace.txt')]
- utils.PrintCmd(retrace_args)
- t0 = time.time()
- subprocess.check_call(retrace_args)
- t1 = time.time()
- if options.print_runtimeraw:
- print('{}(RunTimeRaw): {} ms'
- .format(options.print_runtimeraw, 1000.0 * (t1 - t0)))
-
-
-if __name__ == '__main__':
- options = parse_arguments(sys.argv[1:])
- if options.golem:
- golem.link_third_party()
- if not options.ignore_java_version:
- utils.check_java_version()
- with utils.TempDir() as temp:
- run_retrace(options, temp)
diff --git a/tools/run-d8-on-gmscore.py b/tools/run-d8-on-gmscore.py
index 4a64693..c133bce 100755
--- a/tools/run-d8-on-gmscore.py
+++ b/tools/run-d8-on-gmscore.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/run-jdwp-tests.py b/tools/run-jdwp-tests.py
index f40f2ce..28da012 100755
--- a/tools/run-jdwp-tests.py
+++ b/tools/run-jdwp-tests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
@@ -121,7 +121,7 @@
cmd.extend(get_debuggee_flags(version))
cmd.extend(args)
setup_environment(version)
- print "Running debuggee as:", cmd
+ print("Running debuggee as: %s" % cmd)
return subprocess.check_call(cmd)
def runDebugger(version, classpath, args):
@@ -136,14 +136,14 @@
(dalvikvm, ' '.join(get_debuggee_flags(version))))
cmd.extend(args)
setup_environment(version)
- print "Running debugger as:", cmd
+ print("Running debugger as: " % cmd)
return subprocess.check_call(cmd)
def usage():
- print "Usage: %s [--debuggee] [--version=<version>] [--classpath=<classpath>] <args>" % (sys.argv[0])
- print "where <version> is one of:", ', '.join(VERSIONS)
- print " and <classpath> is optional classpath (default: %s)" % JDWP_TESTS_HOSTDEX
- print " and <args> will be passed on as arguments to the art runtime."
+ print("Usage: %s [--debuggee] [--version=<version>] [--classpath=<classpath>] <args>" % (sys.argv[0]))
+ print("where <version> is one of:", ', '.join(VERSIONS))
+ print(" and <classpath> is optional classpath (default: %s)" % JDWP_TESTS_HOSTDEX)
+ print(" and <args> will be passed on as arguments to the art runtime.")
def main():
version = 'default'
@@ -161,7 +161,7 @@
else:
args.append(arg)
if version not in VERSIONS:
- print "Invalid version", version
+ print("Invalid version %s" % version)
usage()
return 1
if not debuggee and len(args) == 0:
diff --git a/tools/run-r8-on-gmscore.py b/tools/run-r8-on-gmscore.py
index ee8b813..280941e 100755
--- a/tools/run-r8-on-gmscore.py
+++ b/tools/run-r8-on-gmscore.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/run_benchmark.py b/tools/run_benchmark.py
index d5d4fc0..507442e 100755
--- a/tools/run_benchmark.py
+++ b/tools/run_benchmark.py
@@ -99,6 +99,7 @@
'com.android.tools.r8.benchmarks.BenchmarkMainEntryRunner',
options.benchmark,
options.target,
+ 'golem' if options.golem else 'local',
])
return subprocess.check_call(cmd)
diff --git a/tools/run_bootstrap_benchmark.py b/tools/run_bootstrap_benchmark.py
deleted file mode 100755
index bc07347..0000000
--- a/tools/run_bootstrap_benchmark.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-import argparse
-import os
-import sys
-
-import golem
-import minify_tool
-import toolhelper
-import utils
-
-MEMORY_XMX_LIMIT_BENCHMARK = 270
-
-def parse_arguments(argv):
- parser = argparse.ArgumentParser(
- description = 'Run r8 bootstrap benchmarks.')
- parser.add_argument('--golem',
- help = 'Link in third party dependencies.',
- default = False,
- action = 'store_true')
- parser.add_argument('--limit-memory-runtime-test',
- help = 'Run in a specific memory limit.',
- default = False,
- action = 'store_true')
- return parser.parse_args(argv)
-
-
-def dex(input, output):
- return_code = toolhelper.run(
- 'd8', [
- input,
- '--output', output,
- '--lib', utils.RT_JAR,
- '--min-api', '10000',
- '--no-desugaring',
- ],
- debug=False,
- build=False)
- if return_code != 0:
- sys.exit(return_code)
-
-if __name__ == '__main__':
- options = parse_arguments(sys.argv[1:])
- if options.golem:
- golem.link_third_party()
- with utils.TempDir() as temp:
- memory_file = os.path.join(temp, 'memory.dump')
- r8_output = os.path.join(temp, 'r8.zip')
- d8_r8_output = os.path.join(temp, 'd8r8.zip')
- d8_pg_output = os.path.join(temp, 'd8pg.zip')
-
- run_memory_test = options.limit_memory_runtime_test
-
- java_args = (['-Xmx%sM' % MEMORY_XMX_LIMIT_BENCHMARK]
- if run_memory_test else [])
-
- benchmark_name = "MemoryR8Pinned" if run_memory_test else "BootstrapR8"
-
- return_code = minify_tool.minify_tool(
- input_jar=utils.PINNED_R8_JAR,
- output_jar=r8_output,
- debug=False,
- build=False,
- track_memory_file=memory_file,
- benchmark_name=benchmark_name,
- java_args=java_args)
-
- if return_code != 0:
- sys.exit(return_code)
-
- if run_memory_test:
- # We are not tracking code-size, so return early.
- sys.exit(0)
-
- dex(r8_output, d8_r8_output)
- print "BootstrapR8(CodeSize):", utils.uncompressed_size(r8_output)
- print "BootstrapR8Dex(CodeSize):", utils.uncompressed_size(d8_r8_output)
-
- dex(utils.PINNED_PGR8_JAR, d8_pg_output)
- print "BootstrapR8PG(CodeSize):", utils.uncompressed_size(
- utils.PINNED_PGR8_JAR)
- print "BootstrapR8PGDex(CodeSize):", utils.uncompressed_size(d8_pg_output)
-
- r8_notreeshaking_output = os.path.join(temp, 'r8-notreeshaking.zip')
- return_code = minify_tool.minify_tool(
- input_jar=utils.PINNED_R8_JAR,
- output_jar=r8_notreeshaking_output,
- debug=False,
- build=False,
- benchmark_name="BootstrapR8NoTreeShaking",
- additional_args=["--no-tree-shaking"])
- if return_code != 0:
- sys.exit(return_code)
-
- sys.exit(0)
diff --git a/tools/run_kotlin_benchmarks.py b/tools/run_kotlin_benchmarks.py
index 166c3e9..ce0f1ad 100755
--- a/tools/run_kotlin_benchmarks.py
+++ b/tools/run_kotlin_benchmarks.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/sanitize_libraries.py b/tools/sanitize_libraries.py
index 8ca54a7..bc61d50 100755
--- a/tools/sanitize_libraries.py
+++ b/tools/sanitize_libraries.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/test.py b/tools/test.py
index 56f30e7..ec4bb00 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
@@ -219,6 +219,7 @@
if utils.is_bot():
gradle.RunGradle(['--no-daemon', 'clean'])
+ print('Running with python ' + str(sys.version_info))
desugar_jdk_json_dir = None
if options.desugared_library_configuration:
diff --git a/tools/test_android_cts.py b/tools/test_android_cts.py
index fa814bc..f98d724 100755
--- a/tools/test_android_cts.py
+++ b/tools/test_android_cts.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/test_framework.py b/tools/test_framework.py
deleted file mode 100755
index 99e0719..0000000
--- a/tools/test_framework.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2017, 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.
-
-# Run D8 or DX on 'third_party/framework/framework_<version>.jar'.
-# Report Golem-compatible CodeSize and RunTimeRaw values:
-#
-# <NAME>-Total(CodeSize): <size>
-# <NAME>-Total(RunTimeRaw>: <time> ms
-#
-# and also detailed segment sizes for each dex segment:
-#
-# <NAME>-Code(CodeSize): <size>
-# <NAME>-AnnotationSets(CodeSize): <size>
-# ...
-#
-# Uses the DexSegment Java tool (Gradle target).
-
-from __future__ import print_function
-from glob import glob
-import argparse
-import golem
-import jdk
-import os
-import re
-import subprocess
-import sys
-import time
-
-import utils
-
-DX_JAR = os.path.join(utils.REPO_ROOT, 'tools', 'linux', 'dx', 'framework',
- 'dx.jar')
-FRAMEWORK_JAR = os.path.join('third_party', 'framework',
- 'framework_14082017_desugared.jar')
-MIN_SDK_VERSION = '24'
-
-def parse_arguments():
- parser = argparse.ArgumentParser(
- description = 'Run D8 or DX'
- ' third_party/framework/framework*.jar.'
- ' Report Golem-compatible CodeSize and RunTimeRaw values.')
- parser.add_argument('--tool',
- choices = ['dx', 'd8', 'd8-release'],
- required = True,
- help = 'Compiler tool to use.')
- parser.add_argument('--golem',
- help = 'Running on golem, link in third_party resources.',
- default = False,
- action = 'store_true')
- parser.add_argument('--name',
- required = True,
- help = 'Results will be printed using the specified benchmark name (e.g.'
- ' <NAME>-<segment>(CodeSize): <bytes>), the full size is reported'
- ' with <NAME>-Total(CodeSize)')
- parser.add_argument('--print-memoryuse',
- help = 'Prints the line \'<NAME>-Total(MemoryUse):'
- ' <mem>\' at the end where <mem> is the peak'
- ' peak resident set size (VmHWM) in bytes.',
- default = False,
- action = 'store_true')
- parser.add_argument('--output',
- help = 'Output directory to keep the generated files')
- return parser.parse_args()
-
-def Main():
- args = parse_arguments()
- if args.golem:
- golem.link_third_party()
- utils.check_java_version()
- output_dir = args.output
- with utils.TempDir() as temp_dir:
-
- if not output_dir:
- output_dir = temp_dir
-
- xmx = None
- if args.tool == 'dx':
- tool_file = DX_JAR
- tool_args = ['--dex', '--output=' + output_dir, '--multi-dex',
- '--min-sdk-version=' + MIN_SDK_VERSION]
- xmx = '-Xmx1600m'
- else:
- tool_file = utils.D8_JAR
- tool_args = ['--output', output_dir, '--min-api', MIN_SDK_VERSION]
- if args.tool == 'd8-release':
- tool_args.append('--release')
- xmx = '-Xmx600m'
-
- cmd = []
-
- track_memory_file = None
- if args.print_memoryuse:
- track_memory_file = os.path.join(output_dir, utils.MEMORY_USE_TMP_FILE)
- cmd.extend(['tools/track_memory.sh', track_memory_file])
-
- if tool_file.endswith('.jar'):
- assert xmx is not None
- cmd.extend([jdk.GetJavaExecutable(), xmx, '-jar'])
-
- cmd.extend([tool_file] + tool_args + [FRAMEWORK_JAR])
-
- utils.PrintCmd(cmd)
-
- t0 = time.time()
- subprocess.check_call(cmd)
- dt = time.time() - t0
-
- if args.print_memoryuse:
- print('{}-Total(MemoryUse): {}'
- .format(args.name, utils.grep_memoryuse(track_memory_file)))
-
- dex_files = [f for f in glob(os.path.join(output_dir, '*.dex'))]
- code_size = 0
- for dex_file in dex_files:
- code_size += os.path.getsize(dex_file)
-
- print('{}-Total(RunTimeRaw): {} ms'
- .format(args.name, 1000.0 * dt))
-
- print('{}-Total(CodeSize): {}'
- .format(args.name, code_size))
-
- utils.print_dexsegments(args.name, dex_files)
-
-if __name__ == '__main__':
- sys.exit(Main())
diff --git a/tools/test_gradle_benchmarks.py b/tools/test_gradle_benchmarks.py
index b7c53b8..d9c00e6 100755
--- a/tools/test_gradle_benchmarks.py
+++ b/tools/test_gradle_benchmarks.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2018, 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.
diff --git a/tools/test_helloexample.py b/tools/test_helloexample.py
deleted file mode 100755
index f81e64c..0000000
--- a/tools/test_helloexample.py
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2019, 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.
-
-# Run R8 on a simple Hello World program
-# Report Golem-compatible RunTimeRaw values:
-#
-# <NAME>-Total(RunTimeRaw): <time> ms
-#
-# where <NAME> is Hello{,Dex}{,Large}{,NoOpt}
-
-import argparse
-import os
-import subprocess
-import sys
-import time
-import zipfile
-
-import golem
-import jdk
-import proguard
-import utils
-
-HELLO_JAR = os.path.join(utils.BUILD, 'test', 'examples', 'hello.jar')
-
-EXTRA_INPUTS = [
- os.path.join(utils.THIRD_PARTY, 'sample_libraries', lib) for lib in [
- 'animal-sniffer-annotations-1.17.jar',
- 'annotations-13.0.jar',
- 'checker-compat-qual-2.5.2.jar',
- 'collections-28.0.0.jar',
- 'common-1.1.1.jar',
- 'commons-collections4-4.3.jar',
- 'commons-compress-1.18.jar',
- 'commons-lang3-3.8.1.jar',
- 'commons-math3-3.6.1.jar',
- 'constraint-layout-solver-1.1.3.jar',
- 'converter-gson-2.5.0.jar',
- 'dagger-2.22.1.jar',
- 'error_prone_annotations-2.2.0.jar',
- 'failureaccess-1.0.1.jar',
- 'gson-2.8.2.jar',
- 'guava-27.1-android.jar',
- 'j2objc-annotations-1.1.jar',
- 'javax.inject-1.jar',
- 'jsr305-3.0.2.jar',
- 'kotlin-stdlib-1.3.21.jar',
- 'kotlin-stdlib-common-1.3.21.jar',
- 'kotlin-stdlib-jdk7-1.3.21.jar',
- 'listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar',
- 'okhttp-3.14.0.jar',
- 'okio-1.17.2.jar',
- 'play-services-ads-17.2.0-javadoc.jar',
- 'play-services-ads-base-17.2.0-javadoc.jar',
- 'play-services-ads-lite-17.2.0-javadoc.jar',
- 'play-services-analytics-16.0.8-javadoc.jar',
- 'play-services-analytics-impl-16.0.8-javadoc.jar',
- 'play-services-base-16.1.0-javadoc.jar',
- 'play-services-basement-16.2.0-javadoc.jar',
- 'play-services-cast-16.1.2-javadoc.jar',
- 'play-services-drive-16.1.0-javadoc.jar',
- 'play-services-fitness-16.0.1-javadoc.jar',
- 'play-services-games-17.0.0-javadoc.jar',
- 'play-services-gass-17.2.0-javadoc.jar',
- 'play-services-gcm-16.1.0-javadoc.jar',
- 'play-services-iid-16.0.1-javadoc.jar',
- 'play-services-measurement-16.4.0-javadoc.jar',
- 'play-services-measurement-api-16.4.0-javadoc.jar',
- 'play-services-measurement-base-16.4.0-javadoc.jar',
- 'play-services-measurement-impl-16.4.0-javadoc.jar',
- 'play-services-measurement-sdk-16.4.0-javadoc.jar',
- 'play-services-measurement-sdk-api-16.4.0-javadoc.jar',
- 'play-services-tagmanager-v4-impl-16.0.8-javadoc.jar',
- 'play-services-vision-17.0.2-javadoc.jar',
- 'play-services-vision-common-17.0.2-javadoc.jar',
- 'protobuf-lite-3.0.1.jar',
- 'reactive-streams-1.0.2.jar',
- 'retrofit-2.5.0.jar',
- 'rxjava-2.2.8.jar',
- 'support-annotations-28.0.0.jar',
- ]
-]
-
-EXTRA_KEEP_RULES = ['-dontwarn java.lang.ClassValue']
-
-def parse_arguments():
- parser = argparse.ArgumentParser(
- description = 'Compile a hello world example program')
- parser.add_argument('--tool',
- choices = ['d8', 'r8'] + proguard.getVersions(),
- required = True,
- help = 'Compiler tool to use.')
- parser.add_argument('--output-mode',
- choices = ['dex', 'cf'],
- required = True,
- help = 'Output mode to compile to.')
- parser.add_argument('--golem',
- help = 'Running on golem, link in third_party resources.',
- default = False,
- action = 'store_true')
- parser.add_argument('--large',
- help = 'Add many additional program inputs.',
- default = False,
- action = 'store_true')
- parser.add_argument('--noopt',
- help = 'Disable most optimizations/processing.',
- default = False,
- action = 'store_true')
- parser.add_argument('--print-memoryuse',
- help = 'Prints the line \'<NAME>-Total(MemoryUse):'
- ' <mem>\' at the end where <mem> is the peak'
- ' peak resident set size (VmHWM) in bytes.',
- default = False,
- action = 'store_true')
- parser.add_argument('--output',
- help = 'Output directory to keep the generated files')
- return parser.parse_args()
-
-def GetConfRules(extra, noopt):
- rules = ['-keep class hello.Hello { void main(java.lang.String[]); }']
- if len(extra) > 0:
- rules.extend(EXTRA_KEEP_RULES)
- if noopt:
- rules.extend([
- '-dontoptimize',
- '-dontshrink',
- '-dontobfuscate',
- '-keepattributes *',
- ])
- return rules
-
-def GetCompilerPrefix(tool, mode, output, input, lib, extra, noopt):
- return [
- jdk.GetJavaExecutable(),
- '-jar', utils.R8_JAR if tool == 'r8' else utils.D8_JAR,
- '--output', output,
- '--lib', lib,
- '--debug' if noopt else '--release',
- input,
- ] + ([] if mode == 'cf' else ['--min-api', '21']) + extra
-
-def Compile(tool, output_mode, lib, extra, output_dir, noopt, temp_dir):
- output = os.path.join(output_dir, 'out.zip')
- if tool == 'd8':
- if output_mode != 'dex':
- raise ValueError('Invalid output mode for D8')
- classpath = []
- for cp_entry in extra:
- classpath.extend(['--classpath', cp_entry])
- return [
- GetCompilerPrefix(
- tool, output_mode, output, HELLO_JAR, lib, classpath, noopt)
- ]
- # The compilation is either R8 or PG.
- # Write keep rules to a temporary file.
- rules = GetConfRules(extra, noopt)
- rules_file = os.path.join(temp_dir, 'rules.conf')
- open(rules_file, 'w').write('\n'.join(rules))
- if tool == 'r8':
- cmd = GetCompilerPrefix(
- tool, output_mode, output, HELLO_JAR, lib, extra, noopt)
- cmd.extend(['--pg-conf', rules_file])
- if output_mode == 'cf':
- cmd.append('--classfile')
- return [cmd]
- if proguard.isValidVersion(tool):
- # Build PG invokation with additional rules to silence warnings.
- pg_out = output if output_mode == 'cf' \
- else os.path.join(output_dir, 'pgout.zip')
- cmds = [proguard.getCmd([
- '-injars', ':'.join([HELLO_JAR] + extra),
- '-libraryjars', lib,
- '-outjars', pg_out,
- '-dontwarn **',
- '@' + rules_file
- ], version=tool)]
- if output_mode == 'dex':
- cmds.append(
- GetCompilerPrefix('d8', 'dex', output, pg_out, lib, [], noopt))
- return cmds
- raise ValueError('Unknown tool: ' + tool)
-
-def ProcessInput(input, tmp_dir):
- if not input.endswith('.aar'):
- return input
- out_dir = os.path.join(tmp_dir, input)
- os.makedirs(out_dir)
- zip = zipfile.ZipFile(input, 'r')
- zip.extractall(out_dir)
- zip.close()
- return os.path.join(out_dir, 'classes.jar')
-
-def Main():
- args = parse_arguments()
- if args.golem:
- golem.link_third_party()
- utils.check_java_version()
-
- with utils.TempDir() as temp_dir:
- cmd_prefix = []
- output_dir = args.output if args.output else temp_dir
- temp_dir = os.path.join(args.output, 'tmp') if args.output else temp_dir
-
- track_memory_file = None
- if args.print_memoryuse:
- track_memory_file = os.path.join(output_dir, utils.MEMORY_USE_TMP_FILE)
- cmd_prefix.extend(['tools/track_memory.sh', track_memory_file])
-
- name = 'CompileHelloExample'
-
- tool = args.tool
- output_mode = args.output_mode
- lib = None
- if output_mode == 'dex':
- name += 'Dex'
- lib = utils.get_android_jar(28)
- else:
- lib = utils.RT_JAR
-
- extra = []
- if args.large:
- name += 'Large'
- extra = EXTRA_INPUTS
-
- if args.noopt:
- name += 'NoOpt'
-
- cmds = Compile(
- tool,
- output_mode,
- lib,
- extra,
- output_dir,
- args.noopt,
- temp_dir,
- )
-
- t0 = time.time()
- for cmd in cmds:
- fullcmd = cmd_prefix + cmd
- utils.PrintCmd(fullcmd)
- subprocess.check_output(fullcmd)
- dt = time.time() - t0
-
- if args.print_memoryuse:
- print('{}(MemoryUse): {}'
- .format(name, utils.grep_memoryuse(track_memory_file)))
-
- print('{}(RunTimeRaw): {} ms'
- .format(name, 1000.0 * dt))
-
-if __name__ == '__main__':
- sys.exit(Main())
diff --git a/tools/test_r8cfsegments.py b/tools/test_r8cfsegments.py
index 426718a..be8e49c 100755
--- a/tools/test_r8cfsegments.py
+++ b/tools/test_r8cfsegments.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/trigger.py b/tools/trigger.py
index 33b44a7..2b9816a 100755
--- a/tools/trigger.py
+++ b/tools/trigger.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2019, 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.
diff --git a/tools/update_prebuilds_in_android.py b/tools/update_prebuilds_in_android.py
index 3f30964..6f8da19 100755
--- a/tools/update_prebuilds_in_android.py
+++ b/tools/update_prebuilds_in_android.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.
diff --git a/tools/upload_to_x20.py b/tools/upload_to_x20.py
index 2d08362..3a1ef77 100755
--- a/tools/upload_to_x20.py
+++ b/tools/upload_to_x20.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/tools/utils.py b/tools/utils.py
index eb7849b..d616707 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -142,7 +142,7 @@
'show',
tag_or_hash,
'-s',
- '--format=oneline']).splitlines()[-1].split()
+ '--format=oneline']).decode('utf-8').splitlines()[-1].split()
# The info should be on the following form [hash,"Version",version]
if len(info) == 3 and len(info[0]) == 40 and info[1] == "Version":
return info[2]
@@ -310,7 +310,7 @@
def is_main():
remotes = subprocess.check_output(['git', 'branch', '-r', '--contains',
- 'HEAD'])
+ 'HEAD']).decode('utf-8')
return 'origin/main' in remotes
def get_HEAD_sha1():
@@ -359,13 +359,13 @@
def ls_files_on_cloud_storage(destination):
cmd = [get_gsutil(), 'ls', destination]
PrintCmd(cmd)
- return subprocess.check_output(cmd)
+ return subprocess.check_output(cmd).decode('utf-8')
def cat_file_on_cloud_storage(destination, ignore_errors=False):
cmd = [get_gsutil(), 'cat', destination]
PrintCmd(cmd)
try:
- return subprocess.check_output(cmd)
+ return subprocess.check_output(cmd).decode('utf-8').strip()
except subprocess.CalledProcessError as e:
if ignore_errors:
return ''
@@ -535,7 +535,7 @@
'com.android.tools.r8.cf_segments.MeasureLib',
cfFile]
PrintCmd(cmd)
- output = subprocess.check_output(cmd)
+ output = subprocess.check_output(cmd).decode('utf-8')
matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output)
@@ -567,8 +567,8 @@
# Ensure that we are not benchmarking with a google jvm.
def check_java_version():
cmd= [jdk.GetJavaExecutable(), '-version']
- output = subprocess.check_output(cmd, stderr = subprocess.STDOUT)
- m = re.search('openjdk version "([^"]*)"', output.decode('utf-8'))
+ output = subprocess.check_output(cmd, stderr = subprocess.STDOUT).decode('utf-8')
+ m = re.search('openjdk version "([^"]*)"', output)
if m is None:
raise Exception("Can't check java version: no version string in output"
" of 'java -version': '{}'".format(output))
@@ -604,7 +604,7 @@
def getR8Version(path):
cmd = [jdk.GetJavaExecutable(), '-cp', path, 'com.android.tools.r8.R8',
'--version']
- output = subprocess.check_output(cmd, stderr = subprocess.STDOUT)
+ output = subprocess.check_output(cmd, stderr = subprocess.STDOUT).decode('utf-8')
# output is of the form 'R8 <version> (with additional info)'
# so we split on '('; clean up tailing spaces; and strip off 'R8 '.
return output.split('(')[0].strip()[3:]
diff --git a/tools/utils_aosp.py b/tools/utils_aosp.py
index 3e2a715..216e43d 100644
--- a/tools/utils_aosp.py
+++ b/tools/utils_aosp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2017, 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.