Merge commit 'e505f1ebab5a9f698aa94bb583b77eafe93baa6e' into dev-release
diff --git a/build.gradle b/build.gradle
index 433b39a..323256b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1939,6 +1939,10 @@
systemProperty 'slow_tests', project.property('slow_tests')
}
+
+ if (project.hasProperty('desugar_jdk_json_dir')) {
+ systemProperty 'desugar_jdk_json_dir', project.property('desugar_jdk_json_dir')
+ }
if (project.hasProperty('desugar_jdk_libs')) {
systemProperty 'desugar_jdk_libs', project.property('desugar_jdk_libs')
}
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index a4e4210..65521a9 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -425,6 +425,7 @@
name: "kotlin-builder"
mixins: "linux"
mixins: "normal"
+ priority: 27
recipe {
properties_j: "test_options:[\"--not_used\"]"
properties: "test_wrapper:google-scripts/build.py"
diff --git a/src/library_desugar/desugar_jdk_libs_alternative_3.json b/src/library_desugar/desugar_jdk_libs_alternative_3.json
index e23a9b8..2b0ffd9 100644
--- a/src/library_desugar/desugar_jdk_libs_alternative_3.json
+++ b/src/library_desugar/desugar_jdk_libs_alternative_3.json
@@ -77,12 +77,6 @@
"java.time.": "j$.time.",
"java.util.Desugar": "j$.util.Desugar"
},
- "backport": {
- "java.lang.Double8": "java.lang.Double",
- "java.lang.Integer8": "java.lang.Integer",
- "java.lang.Long8": "java.lang.Long",
- "java.lang.Math8": "java.lang.Math"
- },
"retarget_lib_member": {
"java.util.Date#toInstant": "java.util.DesugarDate",
"java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar",
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
new file mode 100644
index 0000000..b0c751c
--- /dev/null
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -0,0 +1,257 @@
+{
+ "configuration_format_version": 3,
+ "group_id" : "com.tools.android",
+ "artifact_id" : "desugar_jdk_libs",
+ "version": "2.0.0",
+ "required_compilation_api_level": 26,
+ "synthesized_library_classes_package_prefix": "j$.",
+ "support_all_callbacks_from_library": true,
+ "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",
+ "sun.misc.Desugar": "j$.sun.misc.Desugar",
+ "jdk.internal.util.Preconditions": "j$.jdk.internal.util.Preconditions"
+ },
+ "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.Helpers": "j$.util.concurrent.Helpers",
+ "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.util.AbstractList": "j$.util.AbstractList",
+ "java.util.CollSer": "j$.util.CollSer",
+ "java.util.ImmutableCollections": "j$.util.ImmutableCollections",
+ "java.util.KeyValueHolder": "j$.util.KeyValueHolder"
+ },
+ "retarget_lib_member": {
+ "java.util.Arrays#stream": "java.util.DesugarArrays",
+ "java.util.Arrays#spliterator": "java.util.DesugarArrays",
+ "java.util.LinkedHashSet#spliterator": "java.util.DesugarLinkedHashSet"
+ },
+ "dont_rewrite": [
+ "java.util.Iterator#remove"
+ ],
+ "emulate_interface": {
+ "java.lang.Iterable": "j$.lang.Iterable",
+ "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.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"
+ },
+ "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"
+ },
+ "dont_rewrite": [
+ "java.util.Iterator#remove"
+ ],
+ "emulate_interface": {
+ "java.lang.Iterable": "j$.lang.Iterable",
+ "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 { 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$.**",
+ "-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_alternative_3.json b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
new file mode 100644
index 0000000..66f3500
--- /dev/null
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
@@ -0,0 +1,260 @@
+{
+ "configuration_format_version": 3,
+ "group_id" : "com.tools.android",
+ "artifact_id" : "desugar_jdk_libs_alternative_3",
+ "version": "2.0.0",
+ "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",
+ "sun.misc.Desugar": "j$.sun.misc.Desugar",
+ "jdk.internal.util.Preconditions": "j$.jdk.internal.util.Preconditions"
+ },
+ "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.Helpers": "j$.util.concurrent.Helpers",
+ "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.util.AbstractList": "j$.util.AbstractList",
+ "java.util.CollSer": "j$.util.CollSer",
+ "java.util.ImmutableCollections": "j$.util.ImmutableCollections",
+ "java.util.KeyValueHolder": "j$.util.KeyValueHolder",
+ "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/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index b12b467..f0cb3e8 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -618,8 +618,9 @@
*
* @param inspection Inspection callback receiving inspectors denoting parts of the output.
*/
- public void addOutputInspection(Consumer<Inspector> inspection) {
+ public B addOutputInspection(Consumer<Inspector> inspection) {
outputInspections.add(inspection);
+ return self();
}
List<Consumer<Inspector>> getOutputInspections() {
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index 740984c..a47844f 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -150,11 +150,11 @@
assert method.getHolderType() == clazz.type;
CfCode code = null;
if (!method.accessFlags.isAbstract() /*&& !method.accessFlags.isNative()*/) {
- code = buildEmptyThrowingCfCode(method.method);
+ code = buildEmptyThrowingCfCode(method.getReference());
}
DexEncodedMethod throwingMethod =
new DexEncodedMethod(
- method.method,
+ method.getReference(),
method.accessFlags,
MethodTypeSignature.noSignature(),
DexAnnotationSet.empty(),
@@ -246,7 +246,7 @@
continue;
}
ProgramMethod implementationMethod =
- implementationClass.lookupProgramMethod(method.method);
+ implementationClass.lookupProgramMethod(method.getReference());
// Don't include methods which are not implemented by the desugared library.
if (supported.test(method) && implementationMethod != null) {
supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
@@ -265,10 +265,10 @@
if (desugaredLibraryConfiguration
.getRetargetCoreLibMember()
.keySet()
- .contains(method.method.name)) {
+ .contains(method.getReference().name)) {
if (desugaredLibraryConfiguration
.getRetargetCoreLibMember()
- .get(method.method.name)
+ .get(method.getReference().name)
.containsKey(clazz.type)) {
if (supported.test(method)) {
supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
@@ -333,8 +333,8 @@
desugaredApisSignatures.add(
classBinaryName
+ '#'
- + method.method.name
- + method.method.proto.toDescriptorString());
+ + method.getReference().name
+ + method.getReference().proto.toDescriptorString());
}
} else {
desugaredApisSignatures.add(classBinaryName);
@@ -405,7 +405,7 @@
return true;
}
assert minApiLevel == AndroidApiLevel.B;
- return !parallelMethods.contains(method.method);
+ return !parallelMethods.contains(method.getReference());
});
}
@@ -585,7 +585,7 @@
}
public String arguments(DexEncodedMethod method) {
- DexProto proto = method.method.proto;
+ DexProto proto = method.getReference().proto;
StringBuilder argsBuilder = new StringBuilder();
boolean firstArg = true;
int argIndex = method.isVirtualMethod() || method.accessFlags.isConstructor() ? 1 : 0;
@@ -685,9 +685,9 @@
builder.appendLiCode(
accessFlags(field.accessFlags)
+ " "
- + typeInPackage(field.field.type)
+ + typeInPackage(field.getReference().type)
+ " "
- + field.field.name);
+ + field.getReference().name);
}
}
if (!constructors.isEmpty()) {
@@ -705,12 +705,12 @@
builder.appendLiCode(
accessFlags(method.accessFlags)
+ " "
- + typeInPackage(method.method.proto.returnType)
+ + typeInPackage(method.getReference().proto.returnType)
+ " "
- + method.method.name
+ + method.getReference().name
+ arguments(method));
- if (parallelMethods.contains(method.method)) {
- parallelM.add(method.method.name.toString());
+ if (parallelMethods.contains(method.getReference())) {
+ parallelM.add(method.getReference().name.toString());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/JarDiff.java b/src/main/java/com/android/tools/r8/JarDiff.java
index a268496..446791f 100644
--- a/src/main/java/com/android/tools/r8/JarDiff.java
+++ b/src/main/java/com/android/tools/r8/JarDiff.java
@@ -145,23 +145,23 @@
private void compareMethods(DexProgramClass class1, DexProgramClass class2) {
class1.forEachMethod(
method1 -> {
- DexEncodedMethod method2 = class2.lookupMethod(method1.method);
+ DexEncodedMethod method2 = class2.lookupMethod(method1.getReference());
compareMethods(method1, method2);
});
class2.forEachMethod(
method2 -> {
- DexEncodedMethod method1 = class1.lookupMethod(method2.method);
+ DexEncodedMethod method1 = class1.lookupMethod(method2.getReference());
compareMethods(method1, method2);
});
}
private void compareMethods(DexEncodedMethod m1, DexEncodedMethod m2) {
if (m1 == null) {
- System.out.println("Only in " + path2 + ": " + m2.method.toSourceString());
+ System.out.println("Only in " + path2 + ": " + m2.getReference().toSourceString());
return;
}
if (m2 == null) {
- System.out.println("Only in " + path1 + ": " + m1.method.toSourceString());
+ System.out.println("Only in " + path1 + ": " + m1.getReference().toSourceString());
return;
}
List<String> code1 = getInstructionStrings(m1);
@@ -176,12 +176,19 @@
int before = Math.min(i, this.before);
int after = Math.min(j, this.after);
int context = before + after;
- System.out.println("--- " + path1 + "/" + m1.method.toSmaliString());
- System.out.println("+++ " + path2 + "/" + m2.method.toSmaliString());
+ System.out.println("--- " + path1 + "/" + m1.getReference().toSmaliString());
+ System.out.println("+++ " + path2 + "/" + m2.getReference().toSmaliString());
System.out.println(
- "@@ -" + (i - before) + "," + (length1 + context)
- + " +" + (i - before) + "," + (length2 + context) + " @@ "
- + m1.method.toSourceString());
+ "@@ -"
+ + (i - before)
+ + ","
+ + (length1 + context)
+ + " +"
+ + (i - before)
+ + ","
+ + (length2 + context)
+ + " @@ "
+ + m1.getReference().toSourceString());
for (int k = 0; k < before; k++) {
System.out.println(" " + code1.get(i - before + k));
}
diff --git a/src/main/java/com/android/tools/r8/JarSizeCompare.java b/src/main/java/com/android/tools/r8/JarSizeCompare.java
index 15e29fa..e520d1b 100644
--- a/src/main/java/com/android/tools/r8/JarSizeCompare.java
+++ b/src/main/java/com/android/tools/r8/JarSizeCompare.java
@@ -332,8 +332,9 @@
MethodSignature originalSignature =
proguardMap == null
? null
- : proguardMap.originalSignatureOf(dexEncodedMethod.method);
- MethodSignature signature = MethodSignature.fromDexMethod(dexEncodedMethod.method);
+ : proguardMap.originalSignatureOf(dexEncodedMethod.getReference());
+ MethodSignature signature =
+ MethodSignature.fromDexMethod(dexEncodedMethod.getReference());
consumer.accept(
originalSignature == null ? signature : originalSignature, dexEncodedMethod);
});
@@ -346,8 +347,10 @@
programClass.forEachField(
dexEncodedField -> {
FieldSignature originalSignature =
- proguardMap == null ? null : proguardMap.originalSignatureOf(dexEncodedField.field);
- FieldSignature signature = FieldSignature.fromDexField(dexEncodedField.field);
+ proguardMap == null
+ ? null
+ : proguardMap.originalSignatureOf(dexEncodedField.getReference());
+ FieldSignature signature = FieldSignature.fromDexField(dexEncodedField.getReference());
consumer.accept(
originalSignature == null ? signature : originalSignature, dexEncodedField);
});
diff --git a/src/main/java/com/android/tools/r8/PrintClassList.java b/src/main/java/com/android/tools/r8/PrintClassList.java
index 73cb04d..1530251 100644
--- a/src/main/java/com/android/tools/r8/PrintClassList.java
+++ b/src/main/java/com/android/tools/r8/PrintClassList.java
@@ -57,7 +57,7 @@
}
private static void printMethod(DexEncodedMethod encodedMethod, ClassNameMapper map) {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
if (map != null) {
System.out.println(map.originalNameOf(method));
} else {
@@ -68,7 +68,7 @@
}
private static void printField(DexEncodedField encodedField, ClassNameMapper map) {
- DexField field = encodedField.field;
+ DexField field = encodedField.getReference();
if (map != null) {
System.out.println(map.originalNameOf(field));
} else {
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index 80b5ec7..926577f 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -108,9 +108,9 @@
ResolutionResult resolutionResult = appInfo.unsafeResolveMethodDueToDexFormat(method);
DexEncodedMethod target =
resolutionResult.isVirtualTarget() ? resolutionResult.getSingleTarget() : null;
- if (target != null && target.method != method) {
+ if (target != null && target.getReference() != method) {
addType(method.holder);
- addMethod(target.method);
+ addMethod(target.getReference());
} else {
addMethod(method);
}
@@ -124,9 +124,9 @@
@Override
public void registerInvokeStatic(DexMethod method) {
DexEncodedMethod target = appInfo.unsafeResolveMethodDueToDexFormat(method).getSingleTarget();
- if (target != null && target.method != method) {
+ if (target != null && target.getReference() != method) {
addType(method.holder);
- addMethod(target.method);
+ addMethod(target.getReference());
} else {
addMethod(method);
}
@@ -204,7 +204,7 @@
addType(field.type);
DexEncodedField baseField = appInfo.resolveField(field).getResolvedField();
if (baseField != null && baseField.getHolderType() != field.holder) {
- field = baseField.field;
+ field = baseField.getReference();
}
addType(field.holder);
Set<DexField> typeFields = fields.get(field.holder);
@@ -245,7 +245,7 @@
}
private void registerField(DexEncodedField field) {
- registerTypeReference(field.field.type);
+ registerTypeReference(field.getReference().type);
}
private void registerMethod(ProgramMethod method) {
@@ -277,10 +277,11 @@
clazz.forEachMethod(
method -> {
ResolutionResult resolutionResult =
- appInfo.resolveMethodOn(superType, method.method, superType != clazz.superType);
+ appInfo.resolveMethodOn(
+ superType, method.getReference(), superType != clazz.superType);
DexEncodedMethod dexEncodedMethod = resolutionResult.getSingleTarget();
if (dexEncodedMethod != null) {
- addMethod(dexEncodedMethod.method);
+ addMethod(dexEncodedMethod.getReference());
}
});
}
@@ -428,7 +429,7 @@
if (encodedMethod.accessFlags.isConstructor()) {
printConstructorName(encodedMethod);
} else {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
append(method.proto.returnType.toSourceString());
append(" ");
append(method.name.toSourceString());
@@ -467,7 +468,7 @@
}
methodDefinitions.add(encodedMethod);
}
- methodDefinitions.sort(Comparator.comparing(x -> x.method.name.toSourceString()));
+ methodDefinitions.sort(Comparator.comparing(x -> x.getReference().name.toSourceString()));
for (DexEncodedMethod encodedMethod : methodDefinitions) {
printMethod(encodedMethod, dexClass.type.toSourceString());
}
@@ -506,7 +507,7 @@
void printMethod(DexEncodedMethod encodedMethod, String typeName) {
append(typeName + ": ");
printNameAndReturn(encodedMethod);
- printArguments(encodedMethod.method);
+ printArguments(encodedMethod.getReference());
appendLine("");
}
@@ -578,13 +579,13 @@
append("static ");
}
printNameAndReturn(encodedMethod);
- printArguments(encodedMethod.method);
+ printArguments(encodedMethod.getReference());
appendLine(";");
}
@Override
void printPackageNames(List<String> packageNames) {
- append("-keeppackagenames " + StringUtils.join(packageNames, ",") + "\n");
+ append("-keeppackagenames " + StringUtils.join(",", packageNames) + "\n");
}
@Override
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index b77c8ed..e6cc1f5 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -46,6 +46,7 @@
import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.ir.desugar.DesugaredLibraryRetargeter;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
+import com.android.tools.r8.ir.desugar.RecordRewriter;
import com.android.tools.r8.ir.optimize.AssertionsRewriter;
import com.android.tools.r8.ir.optimize.MethodPoolCollection;
import com.android.tools.r8.ir.optimize.NestReducer;
@@ -283,7 +284,7 @@
{
ApplicationReader applicationReader = new ApplicationReader(inputApp, options, timing);
DirectMappedDexApplication application = applicationReader.read(executorService).toDirect();
- MainDexInfo mainDexInfo = applicationReader.readMainDexClasses(application);
+ MainDexInfo mainDexInfo = applicationReader.readMainDexClassesForR8(application);
// Now that the dex-application is fully loaded, close any internal archive providers.
inputApp.closeInternalArchiveProviders();
@@ -309,6 +310,9 @@
if (options.enableEnumUnboxing) {
EnumUnboxingCfMethods.registerSynthesizedCodeReferences(appView.dexItemFactory());
}
+ if (options.shouldDesugarRecords()) {
+ RecordRewriter.registerSynthesizedCodeReferences(appView.dexItemFactory());
+ }
CfUtilityMethodsForCodeOptimizations.registerSynthesizedCodeReferences(
appView.dexItemFactory());
@@ -496,7 +500,7 @@
timing.begin("HorizontalClassMerger");
HorizontalClassMerger merger = new HorizontalClassMerger(appViewWithLiveness);
HorizontalClassMergerResult horizontalClassMergerResult =
- merger.run(runtimeTypeCheckInfo);
+ merger.run(runtimeTypeCheckInfo, timing);
if (horizontalClassMergerResult != null) {
// Must rewrite AppInfoWithLiveness before pruning the merged classes, to ensure that
// allocations sites, fields accesses, etc. are correctly transferred to the target
diff --git a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
index d56b873..bc57c25 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -452,7 +452,7 @@
@Override
public void print(CfFrame frame) {
- String keys = join(frame.getLocals().keySet(), ",");
+ String keys = join(",", frame.getLocals().keySet());
String values = join(",", frame.getLocals().values(), this::frameTypeType);
String stack = join(",", frame.getStack(), this::frameTypeType);
printNewInstruction(
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index 9862f27..64dd9a5 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -140,7 +140,7 @@
}
if (method != null) {
builder.append(".method ");
- appendMethod(method.method);
+ appendMethod(method.getReference());
newline();
}
builder.append(".limit stack ").append(code.getMaxStack());
diff --git a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
index ec4b22f..90fc9ee 100644
--- a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
@@ -242,7 +242,8 @@
: createInitializedType(code.method().getHolderType());
} else {
argumentType =
- createInitializedType(code.method().method.proto.parameters.values[argumentIndex]);
+ createInitializedType(
+ code.method().getReference().proto.parameters.values[argumentIndex]);
}
Value outValue = instruction.outValue();
if (outValue.outType().isObject()) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 21de6ac..df1a88b 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
@@ -29,6 +30,7 @@
import com.android.tools.r8.graph.JarClassFileReader;
import com.android.tools.r8.graph.LazyLoadedDexApplication;
import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
@@ -65,6 +67,9 @@
private final Timing timing;
private final AndroidApp inputApp;
+ private boolean hasReadProgramResourcesFromCf = false;
+ private boolean hasReadProgramResourcesFromDex = false;
+
public interface ProgramClassConflictResolver {
DexProgramClass resolveClassConflict(DexProgramClass a, DexProgramClass b);
}
@@ -151,7 +156,9 @@
// TODO: try and preload less classes.
readProguardMap(proguardMap, builder, executorService, futures);
ClassReader classReader = new ClassReader(executorService, futures);
- JarClassFileReader<DexProgramClass> jcf = classReader.readSources();
+ classReader.readSources();
+ hasReadProgramResourcesFromCf = classReader.hasReadProgramResourceFromCf;
+ hasReadProgramResourcesFromDex = classReader.hasReadProgramResourceFromDex;
ThreadUtils.awaitFutures(futures);
classReader.initializeLazyClassCollection(builder);
for (ProgramResourceProvider provider : inputApp.getProgramResourceProviders()) {
@@ -199,17 +206,35 @@
}
public MainDexInfo readMainDexClasses(DexApplication app) {
+ return readMainDexClasses(app, hasReadProgramResourcesFromCf);
+ }
+
+ public MainDexInfo readMainDexClassesForR8(DexApplication app) {
+ // Officially R8 only support reading CF program inputs, thus we always generate a deprecated
+ // diagnostic if main-dex list is used.
+ return readMainDexClasses(app, true);
+ }
+
+ private MainDexInfo readMainDexClasses(DexApplication app, boolean emitDeprecatedDiagnostics) {
MainDexInfo.Builder builder = MainDexInfo.none().builder();
if (inputApp.hasMainDexList()) {
for (StringResource resource : inputApp.getMainDexListResources()) {
+ if (emitDeprecatedDiagnostics) {
+ options.reporter.warning(new UnsupportedMainDexListUsageDiagnostic(resource.getOrigin()));
+ }
addToMainDexClasses(app, builder, MainDexListParser.parseList(resource, itemFactory));
}
- addToMainDexClasses(
- app,
- builder,
- inputApp.getMainDexClasses().stream()
- .map(clazz -> itemFactory.createType(DescriptorUtils.javaTypeToDescriptor(clazz)))
- .collect(Collectors.toList()));
+ if (!inputApp.getMainDexClasses().isEmpty()) {
+ if (emitDeprecatedDiagnostics) {
+ options.reporter.warning(new UnsupportedMainDexListUsageDiagnostic(Origin.unknown()));
+ }
+ addToMainDexClasses(
+ app,
+ builder,
+ inputApp.getMainDexClasses().stream()
+ .map(clazz -> itemFactory.createType(DescriptorUtils.javaTypeToDescriptor(clazz)))
+ .collect(Collectors.toList()));
+ }
}
return builder.buildList();
}
@@ -291,6 +316,13 @@
// Jar application reader to share across all class readers.
private final JarApplicationReader application = new JarApplicationReader(options);
+ // Flag of which input resource types have flowen into the program classes.
+ // Note that this is just at the level of the resources having been given.
+ // It is possible to have, e.g., an empty dex file, so no classes, but this will still be true
+ // as there was a dex resource.
+ private boolean hasReadProgramResourceFromCf = false;
+ private boolean hasReadProgramResourceFromDex = false;
+
ClassReader(ExecutorService executorService, List<Future<?>> futures) {
this.executorService = executorService;
this.futures = futures;
@@ -298,36 +330,42 @@
private void readDexSources(List<ProgramResource> dexSources, Queue<DexProgramClass> classes)
throws IOException, ResourceException {
- if (dexSources.size() > 0) {
- List<DexParser<DexProgramClass>> dexParsers = new ArrayList<>(dexSources.size());
- int computedMinApiLevel = options.minApiLevel;
- for (ProgramResource input : dexSources) {
- DexReader dexReader = new DexReader(input);
- if (options.passthroughDexCode) {
- computedMinApiLevel = validateOrComputeMinApiLevel(computedMinApiLevel, dexReader);
- }
- dexParsers.add(new DexParser<>(dexReader, PROGRAM, options));
+ if (dexSources.isEmpty()) {
+ return;
+ }
+ hasReadProgramResourceFromDex = true;
+ List<DexParser<DexProgramClass>> dexParsers = new ArrayList<>(dexSources.size());
+ int computedMinApiLevel = options.minApiLevel;
+ for (ProgramResource input : dexSources) {
+ DexReader dexReader = new DexReader(input);
+ if (options.passthroughDexCode) {
+ computedMinApiLevel = validateOrComputeMinApiLevel(computedMinApiLevel, dexReader);
}
+ dexParsers.add(new DexParser<>(dexReader, PROGRAM, options));
+ }
- options.minApiLevel = computedMinApiLevel;
+ options.minApiLevel = computedMinApiLevel;
+ for (DexParser<DexProgramClass> dexParser : dexParsers) {
+ dexParser.populateIndexTables();
+ }
+ // Read the DexCode items and DexProgramClass items in parallel.
+ if (!options.skipReadingDexCode) {
for (DexParser<DexProgramClass> dexParser : dexParsers) {
- dexParser.populateIndexTables();
- }
- // Read the DexCode items and DexProgramClass items in parallel.
- if (!options.skipReadingDexCode) {
- for (DexParser<DexProgramClass> dexParser : dexParsers) {
- futures.add(
- executorService.submit(
- () -> {
- dexParser.addClassDefsTo(classes::add); // Depends on Methods, Code items etc.
- }));
- }
+ futures.add(
+ executorService.submit(
+ () -> {
+ dexParser.addClassDefsTo(classes::add); // Depends on Methods, Code items etc.
+ }));
}
}
}
- private JarClassFileReader<DexProgramClass> readClassSources(
+ private void readClassSources(
List<ProgramResource> classSources, Queue<DexProgramClass> classes) {
+ if (classSources.isEmpty()) {
+ return;
+ }
+ hasReadProgramResourceFromCf = true;
JarClassFileReader<DexProgramClass> reader =
new JarClassFileReader<>(application, classes::add, PROGRAM);
// Read classes in parallel.
@@ -341,10 +379,9 @@
return null;
}));
}
- return reader;
}
- JarClassFileReader<DexProgramClass> readSources() throws IOException, ResourceException {
+ void readSources() throws IOException, ResourceException {
Collection<ProgramResource> resources = inputApp.computeAllProgramResources();
List<ProgramResource> dexResources = new ArrayList<>(resources.size());
List<ProgramResource> cfResources = new ArrayList<>(resources.size());
@@ -357,7 +394,7 @@
}
}
readDexSources(dexResources, programClasses);
- return readClassSources(cfResources, programClasses);
+ readClassSources(cfResources, programClasses);
}
private <T extends DexClass> ClassProvider<T> buildClassProvider(
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index cd78995..26bbc5e 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.InstructionFactory;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.ApplicationReaderMap;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexAnnotation;
@@ -79,6 +80,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -992,9 +994,12 @@
private void populateTypes() {
DexSection dexSection = lookupSection(Constants.TYPE_TYPE_ID_ITEM);
assert verifyOrderOfTypeIds(dexSection);
+ Map<DexType, DexType> typeMap = ApplicationReaderMap.getTypeMap(options);
indexedItems.initializeTypes(dexSection.length);
for (int i = 0; i < dexSection.length; i++) {
- indexedItems.setType(i, typeAt(i));
+ DexType type = typeAt(i);
+ DexType actualType = typeMap.getOrDefault(type, type);
+ indexedItems.setType(i, actualType);
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index adfab44..889fc27 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -275,25 +275,25 @@
// static methods, as well as public non-abstract (default)
// and private instance methods.
private void checkInterfaceMethod(DexEncodedMethod method) {
- if (application.dexItemFactory.isClassConstructor(method.method)) {
+ if (application.dexItemFactory.isClassConstructor(method.getReference())) {
return; // Class constructor is always OK.
}
if (method.accessFlags.isStatic()) {
if (!options.canUseDefaultAndStaticInterfaceMethods()
&& !options.testing.allowStaticInterfaceMethodsForPreNApiLevel) {
throw options.reporter.fatalError(
- new StaticInterfaceMethodDiagnostic(new MethodPosition(method.method)));
+ new StaticInterfaceMethodDiagnostic(new MethodPosition(method.getReference())));
}
} else {
if (method.isInstanceInitializer()) {
throw new CompilationError(
- "Interface must not have constructors: " + method.method.toSourceString());
+ "Interface must not have constructors: " + method.getReference().toSourceString());
}
if (!method.accessFlags.isAbstract() && !method.accessFlags.isPrivate() &&
!options.canUseDefaultAndStaticInterfaceMethods()) {
throw options.reporter.fatalError(
- new DefaultInterfaceMethodDiagnostic(new MethodPosition(method.method)));
+ new DefaultInterfaceMethodDiagnostic(new MethodPosition(method.getReference())));
}
}
@@ -302,12 +302,14 @@
return;
}
throw options.reporter.fatalError(
- new PrivateInterfaceMethodDiagnostic(new MethodPosition(method.method)));
+ new PrivateInterfaceMethodDiagnostic(new MethodPosition(method.getReference())));
}
if (!method.accessFlags.isPublic()) {
- throw new CompilationError("Interface methods must not be "
- + "protected or package private: " + method.method.toSourceString());
+ throw new CompilationError(
+ "Interface methods must not be "
+ + "protected or package private: "
+ + method.getReference().toSourceString());
}
}
@@ -636,32 +638,36 @@
private void writeEncodedFields(List<DexEncodedField> unsortedFields) {
List<DexEncodedField> fields = new ArrayList<>(unsortedFields);
- fields.sort((a, b) -> a.field.acceptCompareTo(b.field, mapping.getCompareToVisitor()));
+ fields.sort(
+ (a, b) ->
+ a.getReference().acceptCompareTo(b.getReference(), mapping.getCompareToVisitor()));
int currentOffset = 0;
for (DexEncodedField field : fields) {
assert field.validateDexValue(application.dexItemFactory);
- int nextOffset = mapping.getOffsetFor(field.field);
+ int nextOffset = mapping.getOffsetFor(field.getReference());
assert nextOffset - currentOffset >= 0;
dest.putUleb128(nextOffset - currentOffset);
currentOffset = nextOffset;
dest.putUleb128(field.accessFlags.getAsDexAccessFlags());
- desugaredLibraryCodeToKeep.recordField(field.field);
+ desugaredLibraryCodeToKeep.recordField(field.getReference());
}
}
private void writeEncodedMethods(
Iterable<DexEncodedMethod> unsortedMethods, boolean isSharedSynthetic) {
List<DexEncodedMethod> methods = IterableUtils.toNewArrayList(unsortedMethods);
- methods.sort((a, b) -> a.method.acceptCompareTo(b.method, mapping.getCompareToVisitor()));
+ methods.sort(
+ (a, b) ->
+ a.getReference().acceptCompareTo(b.getReference(), mapping.getCompareToVisitor()));
int currentOffset = 0;
for (DexEncodedMethod method : methods) {
- int nextOffset = mapping.getOffsetFor(method.method);
+ int nextOffset = mapping.getOffsetFor(method.getReference());
assert nextOffset - currentOffset >= 0;
dest.putUleb128(nextOffset - currentOffset);
currentOffset = nextOffset;
dest.putUleb128(method.accessFlags.getAsDexAccessFlags());
DexCode code = codeMapping.getCode(method);
- desugaredLibraryCodeToKeep.recordMethod(method.method);
+ desugaredLibraryCodeToKeep.recordMethod(method.getReference());
if (code == null) {
assert method.shouldNotHaveCode();
dest.putUleb128(0);
diff --git a/src/main/java/com/android/tools/r8/errors/DuplicateTypesDiagnostic.java b/src/main/java/com/android/tools/r8/errors/DuplicateTypesDiagnostic.java
index 1c35883..6aa7234 100644
--- a/src/main/java/com/android/tools/r8/errors/DuplicateTypesDiagnostic.java
+++ b/src/main/java/com/android/tools/r8/errors/DuplicateTypesDiagnostic.java
@@ -64,6 +64,6 @@
@Override
public String getDiagnosticMessage() {
String typeName = DescriptorUtils.descriptorToJavaType(type.getDescriptor());
- return "Type " + typeName + " is defined multiple times: " + StringUtils.join(origins, ", ");
+ return "Type " + typeName + " is defined multiple times: " + StringUtils.join(", ", origins);
}
}
diff --git a/src/main/java/com/android/tools/r8/errors/UnsupportedMainDexListUsageDiagnostic.java b/src/main/java/com/android/tools/r8/errors/UnsupportedMainDexListUsageDiagnostic.java
new file mode 100644
index 0000000..9bcbcba
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/errors/UnsupportedMainDexListUsageDiagnostic.java
@@ -0,0 +1,40 @@
+// 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.errors;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.Keep;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+
+/**
+ * Diagnostic to issue warnings/errors for unsupported usage of main-dex list.
+ *
+ * <p>See b/181858113 for context.
+ */
+@Keep
+public class UnsupportedMainDexListUsageDiagnostic implements Diagnostic {
+ private final Origin origin;
+
+ public UnsupportedMainDexListUsageDiagnostic(Origin origin) {
+ this.origin = origin;
+ }
+
+ @Override
+ public Origin getOrigin() {
+ return origin;
+ }
+
+ @Override
+ public Position getPosition() {
+ return Position.UNKNOWN;
+ }
+
+ @Override
+ public String getDiagnosticMessage() {
+ return "Unsupported usage of main-dex list. "
+ + "The usage of main-dex-list content for the compilation of non-DEX inputs is deprecated. "
+ + "See issue https://issuetracker.google.com/181858113 for context.";
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
index d96643d..c8c462b 100644
--- a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
+++ b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
@@ -159,6 +159,11 @@
public boolean isInBaseOrSameFeatureAs(
DexProgramClass clazz, ProgramDefinition context, SyntheticItems syntheticItems) {
+ return isInBaseOrSameFeatureAs(clazz.getContextType(), context, syntheticItems);
+ }
+
+ public boolean isInBaseOrSameFeatureAs(
+ DexType clazz, ProgramDefinition context, SyntheticItems syntheticItems) {
FeatureSplit split = getFeatureSplit(clazz, syntheticItems);
return split.isBase() || split == getFeatureSplit(context, syntheticItems);
}
diff --git a/src/main/java/com/android/tools/r8/graph/AccessControl.java b/src/main/java/com/android/tools/r8/graph/AccessControl.java
index 51ff1e2..cf2c789 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessControl.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessControl.java
@@ -25,15 +25,16 @@
public static OptionalBool isClassAccessible(
DexClass clazz,
- ProgramDefinition context,
+ Definition context,
ClassToFeatureSplitMap classToFeatureSplitMap,
SyntheticItems syntheticItems) {
if (!clazz.isPublic() && !clazz.getType().isSamePackage(context.getContextType())) {
return OptionalBool.FALSE;
}
if (clazz.isProgramClass()
+ && context.isProgramDefinition()
&& !classToFeatureSplitMap.isInBaseOrSameFeatureAs(
- clazz.asProgramClass(), context, syntheticItems)) {
+ clazz.asProgramClass(), context.asProgramDefinition(), syntheticItems)) {
return OptionalBool.UNKNOWN;
}
return OptionalBool.TRUE;
@@ -47,7 +48,7 @@
return isMemberAccessible(
resolutionResult.getResolutionPair(),
resolutionResult.getInitialResolutionHolder(),
- context,
+ context.getContextClass(),
appInfo);
}
@@ -56,13 +57,14 @@
DexClass initialResolutionHolder,
ProgramDefinition context,
AppView<? extends AppInfoWithClassHierarchy> appView) {
- return isMemberAccessible(member, initialResolutionHolder, context, appView.appInfo());
+ return isMemberAccessible(
+ member, initialResolutionHolder, context.getContextClass(), appView.appInfo());
}
- public static OptionalBool isMemberAccessible(
+ static OptionalBool isMemberAccessible(
DexClassAndMember<?, ?> member,
DexClass initialResolutionHolder,
- ProgramDefinition context,
+ DexClass context,
AppInfoWithClassHierarchy appInfo) {
AccessFlags<?> memberFlags = member.getDefinition().getAccessFlags();
OptionalBool classAccessibility =
@@ -78,25 +80,28 @@
return classAccessibility;
}
if (memberFlags.isPrivate()) {
- if (!isNestMate(member.getHolder(), context.getContextClass())) {
+ if (!isNestMate(member.getHolder(), context)) {
return OptionalBool.FALSE;
}
return classAccessibility;
}
- if (member.getHolderType().isSamePackage(context.getContextType())) {
+ if (member.getHolderType().isSamePackage(context.getType())) {
return classAccessibility;
}
- if (memberFlags.isProtected()
- && appInfo.isSubtype(context.getContextType(), member.getHolderType())) {
+ if (memberFlags.isProtected() && appInfo.isSubtype(context.getType(), member.getHolderType())) {
return classAccessibility;
}
return OptionalBool.FALSE;
}
- private static boolean isNestMate(DexClass clazz, DexProgramClass context) {
+ private static boolean isNestMate(DexClass clazz, DexClass context) {
if (clazz == context) {
return true;
}
+ if (context == null) {
+ assert false : "context should not be null";
+ return false;
+ }
if (!clazz.isInANest() || !context.isInANest()) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index c8d9834..2ee3013 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -455,7 +455,7 @@
}
assert potentialHolder.isInterface();
for (DexEncodedMethod virtualMethod : potentialHolder.virtualMethods()) {
- if (virtualMethod.method.hasSameProtoAndName(method.method)
+ if (virtualMethod.getReference().hasSameProtoAndName(method.getReference())
&& virtualMethod.accessFlags.isSameVisibility(method.accessFlags)) {
return true;
}
@@ -711,7 +711,7 @@
// allowed because of nests, a NoSuchMethodError. Which error cannot be determined without
// knowing the calling context.
if (result.isPrivateMethod() && clazz != initialResolutionHolder) {
- return new IllegalAccessOrNoSuchMethodResult(result);
+ return new IllegalAccessOrNoSuchMethodResult(initialResolutionHolder, result);
}
return new SingleResolutionResult(initialResolutionHolder, clazz, result);
}
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 7622121..7321cc0 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -588,11 +588,11 @@
if (!options().isGeneratingClassFiles()) {
return false;
}
- if (cfByteCodePassThrough.contains(method.method)) {
+ if (cfByteCodePassThrough.contains(method.getReference())) {
return true;
}
return options().testing.cfByteCodePassThrough != null
- && options().testing.cfByteCodePassThrough.test(method.method);
+ && options().testing.cfByteCodePassThrough.test(method.getReference());
}
public boolean hasCfByteCodePassThroughMethods() {
diff --git a/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java b/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java
new file mode 100644
index 0000000..82b9d7f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java
@@ -0,0 +1,31 @@
+// 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.graph;
+
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+public class ApplicationReaderMap {
+
+ public static Map<String, String> getDescriptorMap(InternalOptions options) {
+ ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+ if (options.shouldDesugarRecords()) {
+ builder.put(DexItemFactory.recordTagDescriptorString, DexItemFactory.recordDescriptorString);
+ }
+ return builder.build();
+ }
+
+ public static Map<DexType, DexType> getTypeMap(InternalOptions options) {
+ DexItemFactory factory = options.dexItemFactory();
+ ImmutableMap.Builder<DexType, DexType> builder = ImmutableMap.builder();
+ getDescriptorMap(options)
+ .forEach(
+ (k, v) -> {
+ builder.put(factory.createType(k), factory.createType(v));
+ });
+ return builder.build();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
index 187402a..a05960f 100644
--- a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
@@ -27,7 +27,7 @@
public final class AppliedGraphLens extends NonIdentityGraphLens {
private final MutableBidirectionalManyToOneRepresentativeMap<DexType, DexType> renamedTypeNames =
- new BidirectionalManyToOneRepresentativeHashMap<>();
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
private final BiMap<DexField, DexField> originalFieldSignatures = HashBiMap.create();
private final BiMap<DexMethod, DexMethod> originalMethodSignatures = HashBiMap.create();
@@ -50,7 +50,7 @@
// Record original field signatures.
for (DexEncodedField encodedField : clazz.fields()) {
- DexField field = encodedField.field;
+ DexField field = encodedField.getReference();
DexField original = appView.graphLens().getOriginalFieldSignature(field);
if (original != field) {
DexField existing = originalFieldSignatures.forcePut(field, original);
@@ -60,7 +60,7 @@
// Record original method signatures.
for (DexEncodedMethod encodedMethod : clazz.methods()) {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
DexMethod original = appView.graphLens().getOriginalMethodSignature(method);
DexMethod existing = originalMethodSignatures.inverse().get(original);
if (existing == null) {
diff --git a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
index 1c30bbf..4ed66d8 100644
--- a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
@@ -128,9 +128,10 @@
void writeField(DexEncodedField field, PrintStream ps) {
if (writeFields) {
ClassNameMapper naming = application.getProguardMap();
- FieldSignature fieldSignature = naming != null
- ? naming.originalSignatureOf(field.field)
- : FieldSignature.fromDexField(field.field);
+ FieldSignature fieldSignature =
+ naming != null
+ ? naming.originalSignatureOf(field.getReference())
+ : FieldSignature.fromDexField(field.getReference());
writeAnnotations(null, field.annotations(), ps);
ps.print(field.accessFlags + " ");
ps.print(fieldSignature);
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 71b938f..315bb3e 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -300,7 +300,7 @@
}
// If tree shaking, only keep annotations on kept methods.
if (appView.appInfo().hasLiveness()
- && !appView.appInfo().withLiveness().isPinned(method.method)) {
+ && !appView.appInfo().withLiveness().isPinned(method.getReference())) {
return false;
}
return true;
@@ -575,7 +575,7 @@
// The enqueuer might build IR to trace reflective behaviour. At that point liveness is not
// known, so be conservative with collection parameter name information.
if (appView.appInfo().hasLiveness()
- && !appView.appInfo().withLiveness().isPinned(encodedMethod.method)) {
+ && !appView.appInfo().withLiveness().isPinned(encodedMethod.getReference())) {
return DexEncodedMethod.NO_PARAMETER_INFO;
}
@@ -585,7 +585,7 @@
if (!encodedMethod.isStatic()) {
localSlotsForParameters.set(nextLocalSlotsForParameters++);
}
- for (DexType type : encodedMethod.method.proto.parameters.values) {
+ for (DexType type : encodedMethod.getReference().proto.parameters.values) {
localSlotsForParameters.set(nextLocalSlotsForParameters);
nextLocalSlotsForParameters += type.isLongType() || type.isDoubleType() ? 2 : 1;
}
@@ -607,7 +607,7 @@
@Override
public void registerArgumentReferences(DexEncodedMethod method, ArgumentUse registry) {
- DexProto proto = method.method.proto;
+ DexProto proto = method.getReference().proto;
boolean isStatic = method.accessFlags.isStatic();
int argumentCount = proto.parameters.values.length + (isStatic ? 0 : 1);
Int2IntArrayMap indexToNumber = new Int2IntArrayMap(argumentCount);
@@ -728,7 +728,7 @@
if (!method.isInstanceInitializer()
&& appView
.graphLens()
- .getOriginalMethodSignature(method.method)
+ .getOriginalMethodSignature(method.getReference())
.isInstanceInitializer(appView.dexItemFactory())) {
// We cannot verify instance initializers if they are moved.
return StackMapStatus.NOT_PRESENT;
@@ -746,7 +746,7 @@
return reportStackMapError(
CfCodeStackMapValidatingException.multipleFramesForLabel(
origin,
- appView.graphLens().getOriginalMethodSignature(method.method),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
appView),
appView);
}
@@ -756,7 +756,9 @@
// From b/168212806, it is possible that the first instruction is a frame.
return reportStackMapError(
CfCodeStackMapValidatingException.unexpectedStackMapFrame(
- origin, appView.graphLens().getOriginalMethodSignature(method.method), appView),
+ origin,
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ appView),
appView);
}
}
@@ -777,15 +779,17 @@
if (requireStackMapFrame && stateMap.isEmpty()) {
return reportStackMapError(
CfCodeStackMapValidatingException.noFramesForMethodWithJumps(
- origin, appView.graphLens().getOriginalMethodSignature(method.method), appView),
+ origin,
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ appView),
appView);
}
DexType context = appView.graphLens().lookupType(method.getHolderType());
- DexType returnType = appView.graphLens().lookupType(method.method.getReturnType());
+ DexType returnType = appView.graphLens().lookupType(method.getReference().getReturnType());
RewrittenPrototypeDescription rewrittenDescription = RewrittenPrototypeDescription.none();
if (applyProtoTypeChanges) {
rewrittenDescription =
- appView.graphLens().lookupPrototypeChangesForMethodDefinition(method.method);
+ appView.graphLens().lookupPrototypeChangesForMethodDefinition(method.getReference());
if (!rewrittenDescription.isEmpty()
&& rewrittenDescription.getRewrittenReturnInfo() != null) {
returnType = rewrittenDescription.getRewrittenReturnInfo().getOldType();
@@ -824,7 +828,7 @@
return reportStackMapError(
CfCodeStackMapValidatingException.toDiagnostics(
origin,
- appView.graphLens().getOriginalMethodSignature(method.method),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
i,
instruction,
ex.getMessage(),
@@ -889,7 +893,7 @@
initialLocals.put(index++, FrameType.initialized(context));
}
ArgumentInfoCollection argumentsInfo = protoTypeChanges.getArgumentInfoCollection();
- DexType[] parameters = method.method.proto.parameters.values;
+ DexType[] parameters = method.getReference().proto.parameters.values;
int originalNumberOfArguments =
parameters.length
+ argumentsInfo.numberOfRemovedArguments()
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
index ad9bf23..d2d763e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -46,17 +46,18 @@
}
public List<DexEncodedMethod> sortMethodAnnotations(CompareToVisitor visitor) {
- methodAnnotations.sort((a, b) -> a.method.acceptCompareTo(b.method, visitor));
+ methodAnnotations.sort((a, b) -> a.getReference().acceptCompareTo(b.getReference(), visitor));
return methodAnnotations;
}
public List<DexEncodedMethod> sortParameterAnnotations(CompareToVisitor visitor) {
- parameterAnnotations.sort((a, b) -> a.method.acceptCompareTo(b.method, visitor));
+ parameterAnnotations.sort(
+ (a, b) -> a.getReference().acceptCompareTo(b.getReference(), visitor));
return parameterAnnotations;
}
public List<DexEncodedField> sortFieldAnnotations(CompareToVisitor visitor) {
- fieldAnnotations.sort((a, b) -> a.field.acceptCompareTo(b.field, visitor));
+ fieldAnnotations.sort((a, b) -> a.getReference().acceptCompareTo(b.getReference(), visitor));
return fieldAnnotations;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 130dbcf..b2bc948 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -10,6 +10,9 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.references.ClassReference;
@@ -20,6 +23,7 @@
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
@@ -31,6 +35,7 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -257,7 +262,9 @@
if (options.canHaveDalvikAbstractMethodOnNonAbstractClassVerificationBug() && !isAbstract()) {
for (DexEncodedMethod method : methods) {
assert !method.isAbstract()
- : "Non-abstract method on abstract class: `" + method.method.toSourceString() + "`";
+ : "Non-abstract method on abstract class: `"
+ + method.getReference().toSourceString()
+ + "`";
}
}
return true;
@@ -363,7 +370,7 @@
public boolean definesStaticField(DexField field) {
for (DexEncodedField encodedField : staticFields()) {
- if (encodedField.field == field) {
+ if (encodedField.getReference() == field) {
return true;
}
}
@@ -427,7 +434,7 @@
private boolean verifyCorrectnessOfFieldHolder(DexEncodedField field) {
assert field.getHolderType() == type
: "Expected field `"
- + field.field.toSourceString()
+ + field.getReference().toSourceString()
+ "` to have holder `"
+ type.toSourceString()
+ "`";
@@ -444,8 +451,8 @@
private boolean verifyNoDuplicateFields() {
Set<DexField> unique = Sets.newIdentityHashSet();
for (DexEncodedField field : fields()) {
- boolean changed = unique.add(field.field);
- assert changed : "Duplicate field `" + field.field.toSourceString() + "`";
+ boolean changed = unique.add(field.getReference());
+ assert changed : "Duplicate field `" + field.getReference().toSourceString() + "`";
}
return true;
}
@@ -463,11 +470,11 @@
public DexField lookupUniqueInstanceFieldWithName(DexString name) {
DexField field = null;
for (DexEncodedField encodedField : instanceFields()) {
- if (encodedField.field.name == name) {
+ if (encodedField.getReference().name == name) {
if (field != null) {
return null;
}
- field = encodedField.field;
+ field = encodedField.getReference();
}
}
return field;
@@ -544,7 +551,7 @@
DexEncodedMethod matchingName = null;
DexEncodedMethod signaturePolymorphicMethod = null;
for (DexEncodedMethod method : virtualMethods()) {
- if (method.method.name == methodName) {
+ if (method.getReference().name == methodName) {
if (matchingName != null) {
// The jvm spec, section 5.4.3.3 details that there must be exactly one method with the
// given name only.
@@ -564,8 +571,8 @@
|| method.getHolderType() == factory.varHandleType;
return method.accessFlags.isVarargs()
&& method.accessFlags.isNative()
- && method.method.proto.parameters.size() == 1
- && method.method.proto.parameters.values[0] != factory.objectArrayType;
+ && method.getReference().proto.parameters.size() == 1
+ && method.getReference().proto.parameters.values[0] != factory.objectArrayType;
}
private <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>> D lookupTarget(
@@ -704,7 +711,7 @@
public DexEncodedMethod getInitializer(DexType[] parameters) {
for (DexEncodedMethod method : directMethods()) {
if (method.isInstanceInitializer()
- && Arrays.equals(method.method.proto.parameters.values, parameters)) {
+ && Arrays.equals(method.getReference().proto.parameters.values, parameters)) {
return method;
}
}
@@ -778,13 +785,125 @@
Predicate<DexType> ignore,
Set<DexType> seen);
+ public void forEachImmediateInterface(Consumer<DexType> fn) {
+ for (DexType iface : interfaces.values) {
+ fn.accept(iface);
+ }
+ }
+
public void forEachImmediateSupertype(Consumer<DexType> fn) {
if (superType != null) {
fn.accept(superType);
}
- for (DexType iface : interfaces.values) {
- fn.accept(iface);
+ forEachImmediateInterface(fn);
+ }
+
+ public boolean validInterfaceSignatures() {
+ return getClassSignature().superInterfaceSignatures().isEmpty()
+ || interfaces.values.length == getClassSignature().superInterfaceSignatures.size();
+ }
+
+ public void forEachImmediateInterface(BiConsumer<DexType, ClassTypeSignature> consumer) {
+ assert validInterfaceSignatures();
+
+ // If there is no generic signature information don't pass any type arguments.
+ if (getClassSignature().superInterfaceSignatures().isEmpty()) {
+ forEachImmediateInterface(
+ superInterface ->
+ consumer.accept(superInterface, new ClassTypeSignature(superInterface)));
+ return;
}
+
+ Iterator<DexType> interfaceIterator = Arrays.asList(interfaces.values).iterator();
+ Iterator<ClassTypeSignature> interfaceSignatureIterator =
+ getClassSignature().superInterfaceSignatures().iterator();
+
+ while (interfaceIterator.hasNext()) {
+ assert interfaceSignatureIterator.hasNext();
+ DexType superInterface = interfaceIterator.next();
+ ClassTypeSignature superInterfaceSignatures = interfaceSignatureIterator.next();
+ consumer.accept(superInterface, superInterfaceSignatures);
+ }
+ }
+
+ public void forEachImmediateSupertype(BiConsumer<DexType, ClassTypeSignature> consumer) {
+ if (superType != null) {
+ consumer.accept(superType, classSignature.superClassSignature);
+ }
+ forEachImmediateInterface(consumer);
+ }
+
+ public void forEachImmediateInterfaceWithAppliedTypeArguments(
+ List<FieldTypeSignature> typeArguments,
+ BiConsumer<DexType, List<FieldTypeSignature>> consumer) {
+ assert validInterfaceSignatures();
+
+ // If there is no generic signature information don't pass any type arguments.
+ if (getClassSignature().superInterfaceSignatures().size() == 0) {
+ forEachImmediateInterface(
+ superInterface -> consumer.accept(superInterface, ImmutableList.of()));
+ return;
+ }
+
+ Iterator<DexType> interfaceIterator = Arrays.asList(interfaces.values).iterator();
+ Iterator<ClassTypeSignature> interfaceSignatureIterator =
+ getClassSignature().superInterfaceSignatures().iterator();
+
+ while (interfaceIterator.hasNext()) {
+ assert interfaceSignatureIterator.hasNext();
+ DexType superInterface = interfaceIterator.next();
+ ClassTypeSignature superInterfaceSignatures = interfaceSignatureIterator.next();
+
+ // With no type arguments erase the signatures.
+ if (typeArguments.isEmpty() && superInterfaceSignatures.hasTypeVariableArguments()) {
+ consumer.accept(superInterface, ImmutableList.of());
+ continue;
+ }
+
+ consumer.accept(superInterface, applyTypeArguments(superInterfaceSignatures, typeArguments));
+ }
+ assert !interfaceSignatureIterator.hasNext();
+ }
+
+ public void forEachImmediateSupertypeWithAppliedTypeArguments(
+ List<FieldTypeSignature> typeArguments,
+ BiConsumer<DexType, List<FieldTypeSignature>> consumer) {
+ if (superType != null) {
+ consumer.accept(
+ superType, applyTypeArguments(getClassSignature().superClassSignature, typeArguments));
+ }
+ forEachImmediateInterfaceWithAppliedTypeArguments(typeArguments, consumer);
+ }
+
+ private List<FieldTypeSignature> applyTypeArguments(
+ ClassTypeSignature superInterfaceSignatures, List<FieldTypeSignature> appliedTypeArguments) {
+ ImmutableList.Builder<FieldTypeSignature> superTypeArgumentsBuilder = ImmutableList.builder();
+ if (superInterfaceSignatures.type.toSourceString().equals("java.util.Map")) {
+ System.currentTimeMillis();
+ }
+ superInterfaceSignatures
+ .typeArguments()
+ .forEach(
+ typeArgument -> {
+ if (typeArgument.isTypeVariableSignature()) {
+ for (int i = 0; i < getClassSignature().getFormalTypeParameters().size(); i++) {
+ FormalTypeParameter formalTypeParameter =
+ getClassSignature().getFormalTypeParameters().get(i);
+ if (formalTypeParameter
+ .getName()
+ .equals(typeArgument.asTypeVariableSignature().typeVariable())) {
+ if (i >= appliedTypeArguments.size()) {
+ assert false;
+ } else {
+ superTypeArgumentsBuilder.add(appliedTypeArguments.get(i));
+ }
+ }
+ }
+ } else {
+ superTypeArgumentsBuilder.add(typeArgument);
+ }
+ });
+ return superTypeArgumentsBuilder.build();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
index 32743f0..09bc3b7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
@@ -63,11 +63,11 @@
}
public DexDebugEntryBuilder(DexEncodedMethod method, DexItemFactory factory) {
- assert method != null && method.method != null;
- this.method = method.method;
+ assert method != null && method.getReference() != null;
+ this.method = method.getReference();
positionState =
new DexDebugPositionState(
- method.getCode().asDexCode().getDebugInfo().startLine, method.method);
+ method.getCode().asDexCode().getDebugInfo().startLine, method.getReference());
DexCode code = method.getCode().asDexCode();
DexDebugInfo info = code.getDebugInfo();
int argumentRegister = code.registerSize - code.incomingRegisterSize;
@@ -77,7 +77,7 @@
startArgument(argumentRegister, name, type);
argumentRegister += ValueType.fromDexType(type).requiredRegisters();
}
- DexType[] types = method.method.proto.parameters.values;
+ DexType[] types = method.getReference().proto.parameters.values;
DexString[] names = info.parameters;
for (int i = 0; i < types.length; i++) {
// If null, the parameter has a parameterized type and the local is introduced in the stream.
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index f166e3c..bdfe991 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -110,7 +110,7 @@
if (startLine == NO_LINE_INFO) {
return null;
}
- DexString[] params = new DexString[method.method.getArity()];
+ DexString[] params = new DexString[method.getReference().getArity()];
if (arguments != null) {
assert params.length == arguments.size();
for (int i = 0; i < arguments.size(); i++) {
@@ -158,7 +158,7 @@
private void startArgument(Argument argument) {
if (arguments == null) {
- arguments = new ArrayList<>(method.method.getArity());
+ arguments = new ArrayList<>(method.getReference().getArity());
}
if (!argument.outValue().isThis()) {
arguments.add(argument.getLocalInfo());
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index 1a2b411..65bc4fb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -31,7 +31,6 @@
implements StructuralItem<DexEncodedField> {
public static final DexEncodedField[] EMPTY_ARRAY = {};
- public final DexField field;
public final FieldAccessFlags accessFlags;
private DexValue staticValue;
private final boolean deprecated;
@@ -42,10 +41,10 @@
private KotlinFieldLevelInfo kotlinMemberInfo = NO_KOTLIN_INFO;
private static void specify(StructuralSpecification<DexEncodedField, ?> spec) {
- spec.withItem(f -> f.field)
- .withItem(f -> f.accessFlags)
+ spec.withItem(DexEncodedField::getReference)
+ .withItem(DexEncodedField::getAccessFlags)
.withNullableItem(f -> f.staticValue)
- .withBool(f -> f.deprecated)
+ .withBool(DexEncodedField::isDeprecated)
// TODO(b/171867022): The generic signature should be part of the definition.
.withAssert(f -> f.genericSignature.hasNoSignature());
// TODO(b/171867022): Should the optimization info and member info be part of the definition?
@@ -82,8 +81,7 @@
DexValue staticValue,
boolean deprecated,
boolean d8R8Synthesized) {
- super(annotations, d8R8Synthesized);
- this.field = field;
+ super(field, annotations, d8R8Synthesized);
this.accessFlags = accessFlags;
this.staticValue = staticValue;
this.deprecated = deprecated;
@@ -103,7 +101,7 @@
}
public DexType type() {
- return field.type;
+ return getReference().type;
}
public boolean isDeprecated() {
@@ -111,8 +109,8 @@
}
public boolean isProgramField(DexDefinitionSupplier definitions) {
- if (field.holder.isClassType()) {
- DexClass clazz = definitions.definitionFor(field.holder);
+ if (getReference().holder.isClassType()) {
+ DexClass clazz = definitions.definitionFor(getReference().holder);
return clazz != null && clazz.isProgramClass();
}
return false;
@@ -158,22 +156,17 @@
@Override
public String toString() {
- return "Encoded field " + field;
+ return "Encoded field " + getReference();
}
@Override
public String toSmaliString() {
- return field.toSmaliString();
+ return getReference().toSmaliString();
}
@Override
public String toSourceString() {
- return field.toSourceString();
- }
-
- @Override
- public DexField getReference() {
- return field;
+ return getReference().toSourceString();
}
public DexType getType() {
@@ -201,7 +194,7 @@
public ProgramField asProgramField(DexDefinitionSupplier definitions) {
assert getHolderType().isClassType();
- DexProgramClass clazz = asProgramClassOrNull(definitions.definitionForHolder(field));
+ DexProgramClass clazz = asProgramClassOrNull(definitions.definitionForHolder(getReference()));
if (clazz != null) {
return new ProgramField(clazz, this);
}
@@ -264,7 +257,7 @@
public DexValue getStaticValue() {
assert accessFlags.isStatic();
- return staticValue == null ? DexValue.defaultForType(field.type) : staticValue;
+ return staticValue == null ? DexValue.defaultForType(getReference().type) : staticValue;
}
/**
@@ -277,7 +270,7 @@
boolean isWritten = appView.appInfo().isFieldWrittenByFieldPutInstruction(this);
if (!isWritten) {
// Since the field is not written, we can simply return the default value for the type.
- DexValue value = isStatic() ? getStaticValue() : DexValue.defaultForType(field.type);
+ DexValue value = isStatic() ? getStaticValue() : DexValue.defaultForType(getReference().type);
return value.asConstInstruction(appView, code, local);
}
@@ -286,11 +279,11 @@
if (abstractValue.isSingleValue()) {
SingleValue singleValue = abstractValue.asSingleValue();
if (singleValue.isSingleFieldValue()
- && singleValue.asSingleFieldValue().getField() == field) {
+ && singleValue.asSingleFieldValue().getField() == getReference()) {
return null;
}
if (singleValue.isMaterializableInContext(appView, code.context())) {
- TypeElement type = TypeElement.fromDexType(field.type, maybeNull(), appView);
+ TypeElement type = TypeElement.fromDexType(getReference().type, maybeNull(), appView);
return singleValue.createMaterializingInstruction(
appView, code, TypeAndLocalInfoSupplier.create(type, local));
}
@@ -299,12 +292,12 @@
// The only way to figure out whether the static value contains the final value is ensure the
// value is not the default or check that <clinit> is not present.
if (accessFlags.isFinal() && isStatic()) {
- DexClass clazz = appView.definitionFor(field.holder);
+ DexClass clazz = appView.definitionFor(getReference().holder);
if (clazz == null || clazz.hasClassInitializer()) {
return null;
}
DexValue staticValue = getStaticValue();
- if (!staticValue.isDefault(field.type)) {
+ if (!staticValue.isDefault(getReference().type)) {
return staticValue.asConstInstruction(appView, code, local);
}
}
@@ -317,7 +310,7 @@
}
public DexEncodedField toTypeSubstitutedField(DexField field, Consumer<Builder> consumer) {
- if (this.field == field) {
+ if (this.getReference() == field) {
return this;
}
return builder(this).setField(field).apply(consumer).build();
@@ -327,12 +320,13 @@
if (!accessFlags.isStatic() || staticValue == null) {
return true;
}
- if (field.type.isPrimitiveType()) {
- assert staticValue.getType(factory) == field.type
- : "Static " + field + " has invalid static value " + staticValue + ".";
+ if (getReference().type.isPrimitiveType()) {
+ assert staticValue.getType(factory) == getReference().type
+ : "Static " + getReference() + " has invalid static value " + staticValue + ".";
}
if (staticValue.isDexValueNull()) {
- assert field.type.isReferenceType() : "Static " + field + " has invalid null static value.";
+ assert getReference().type.isReferenceType()
+ : "Static " + getReference() + " has invalid null static value.";
}
// TODO(b/150593449): Support non primitive DexValue (String, enum) and add assertions.
return true;
@@ -369,7 +363,7 @@
Builder(DexEncodedField from) {
// Copy all the mutable state of a DexEncodedField here.
- field = from.field;
+ field = from.getReference();
accessFlags = from.accessFlags.copy();
// TODO(b/169923358): Consider removing the fieldSignature here.
genericSignature = from.getGenericSignature();
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
index 7d66bb6..0074842 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
@@ -16,8 +16,11 @@
// set.
private final boolean d8R8Synthesized;
- public DexEncodedMember(DexAnnotationSet annotations, boolean d8R8Synthesized) {
+ private final R reference;
+
+ public DexEncodedMember(R reference, DexAnnotationSet annotations, boolean d8R8Synthesized) {
super(annotations);
+ this.reference = reference;
this.d8R8Synthesized = d8R8Synthesized;
}
@@ -32,7 +35,9 @@
}
@Override
- public abstract R getReference();
+ public R getReference() {
+ return reference;
+ }
public boolean isD8R8Synthesized() {
return d8R8Synthesized;
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 470bee9..d387d77 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -150,7 +150,6 @@
public static final Int2ReferenceMap<DebugLocalInfo> NO_PARAMETER_INFO =
new Int2ReferenceArrayMap<>(0);
- public final DexMethod method;
public final MethodAccessFlags accessFlags;
public final boolean deprecated;
public ParameterAnnotationsList parameterAnnotationsList;
@@ -311,8 +310,7 @@
boolean d8R8Synthesized,
CfVersion classFileVersion,
boolean deprecated) {
- super(annotations, d8R8Synthesized);
- this.method = method;
+ super(method, annotations, d8R8Synthesized);
this.accessFlags = accessFlags;
this.deprecated = deprecated;
this.genericSignature = genericSignature;
@@ -383,12 +381,6 @@
return getReference().getProto();
}
- @Override
- public DexMethod getReference() {
- checkIfObsolete();
- return method;
- }
-
public DexType getParameter(int index) {
return getReference().getParameter(index);
}
@@ -398,11 +390,11 @@
}
public DexMethodSignature getSignature() {
- return new DexMethodSignature(method);
+ return new DexMethodSignature(getReference());
}
public DexType returnType() {
- return method.proto.returnType;
+ return getReference().proto.returnType;
}
public ParameterAnnotationsList liveParameterAnnotations(AppView<AppInfoWithLiveness> appView) {
@@ -420,19 +412,19 @@
assert isLibraryMethodOverride.isPossiblyFalse()
|| this.isLibraryMethodOverride.isPossiblyTrue()
: "Method `"
- + method.toSourceString()
+ + getReference().toSourceString()
+ "` went from not overriding a library method to overriding a library method";
assert isLibraryMethodOverride.isPossiblyTrue()
|| this.isLibraryMethodOverride.isPossiblyFalse()
: "Method `"
- + method.toSourceString()
+ + getReference().toSourceString()
+ "` went from overriding a library method to not overriding a library method";
this.isLibraryMethodOverride = isLibraryMethodOverride;
}
public boolean isProgramMethod(DexDefinitionSupplier definitions) {
- if (method.holder.isClassType()) {
- DexClass clazz = definitions.definitionFor(method.holder);
+ if (getReference().holder.isClassType()) {
+ DexClass clazz = definitions.definitionFor(getReference().holder);
return clazz != null && clazz.isProgramClass();
}
return false;
@@ -444,8 +436,8 @@
}
public DexClassAndMethod asDexClassAndMethod(DexDefinitionSupplier definitions) {
- assert method.holder.isClassType();
- DexClass clazz = definitions.definitionForHolder(method);
+ assert getReference().holder.isClassType();
+ DexClass clazz = definitions.definitionForHolder(getReference());
if (clazz != null) {
return DexClassAndMethod.create(clazz, this);
}
@@ -453,8 +445,8 @@
}
public ProgramMethod asProgramMethod(DexDefinitionSupplier definitions) {
- assert method.holder.isClassType();
- DexProgramClass clazz = asProgramClassOrNull(definitions.definitionForHolder(method));
+ assert getReference().holder.isClassType();
+ DexProgramClass clazz = asProgramClassOrNull(definitions.definitionForHolder(getReference()));
if (clazz != null) {
return new ProgramMethod(clazz, this);
}
@@ -530,7 +522,7 @@
public boolean isDefaultInitializer() {
checkIfObsolete();
- return isInstanceInitializer() && method.proto.parameters.isEmpty();
+ return isInstanceInitializer() && getReference().proto.parameters.isEmpty();
}
public boolean isClassInitializer() {
@@ -698,28 +690,28 @@
return true;
case PROCESSED_INLINING_CANDIDATE_SUBCLASS:
- if (appInfo.isSubtype(containerType, method.holder)) {
+ if (appInfo.isSubtype(containerType, getReference().holder)) {
return true;
}
whyAreYouNotInliningReporter.reportCallerNotSubtype();
return false;
case PROCESSED_INLINING_CANDIDATE_SAME_PACKAGE:
- if (containerType.isSamePackage(method.holder)) {
+ if (containerType.isSamePackage(getReference().holder)) {
return true;
}
whyAreYouNotInliningReporter.reportCallerNotSamePackage();
return false;
case PROCESSED_INLINING_CANDIDATE_SAME_NEST:
- if (NestUtils.sameNest(containerType, method.holder, appInfo)) {
+ if (NestUtils.sameNest(containerType, getReference().holder, appInfo)) {
return true;
}
whyAreYouNotInliningReporter.reportCallerNotSameNest();
return false;
case PROCESSED_INLINING_CANDIDATE_SAME_CLASS:
- if (containerType == method.holder) {
+ if (containerType == getReference().holder) {
return true;
}
whyAreYouNotInliningReporter.reportCallerNotSameClass();
@@ -808,7 +800,7 @@
@Override
public String toString() {
checkIfObsolete();
- return "Encoded method " + method;
+ return "Encoded method " + getReference();
}
@Override
@@ -869,7 +861,7 @@
public String qualifiedName() {
checkIfObsolete();
- return method.qualifiedName();
+ return getReference().qualifiedName();
}
public String descriptor() {
@@ -881,11 +873,11 @@
checkIfObsolete();
StringBuilder builder = new StringBuilder();
builder.append("(");
- for (DexType type : method.proto.parameters.values) {
+ for (DexType type : getReference().proto.parameters.values) {
builder.append(namingLens.lookupDescriptor(type).toString());
}
builder.append(")");
- builder.append(namingLens.lookupDescriptor(method.proto.returnType).toString());
+ builder.append(namingLens.lookupDescriptor(getReference().proto.returnType).toString());
return builder.toString();
}
@@ -903,8 +895,8 @@
builder.append(".method ");
builder.append(accessFlags.toSmaliString());
builder.append(" ");
- builder.append(method.name.toSmaliString());
- builder.append(method.proto.toSmaliString());
+ builder.append(getReference().name.toSmaliString());
+ builder.append(getReference().proto.toSmaliString());
builder.append("\n");
if (code != null) {
DexCode dexCode = code.asDexCode();
@@ -920,7 +912,7 @@
@Override
public String toSourceString() {
checkIfObsolete();
- return method.toSourceString();
+ return getReference().toSourceString();
}
public DexEncodedMethod toAbstractMethod() {
@@ -946,7 +938,7 @@
offset += instruction.getSize();
}
int requiredArgRegisters = accessFlags.isStatic() ? 0 : 1;
- for (DexType type : method.proto.parameters.values) {
+ for (DexType type : getReference().proto.parameters.values) {
requiredArgRegisters += ValueType.fromDexType(type).requiredRegisters();
}
return new DexCode(
@@ -998,7 +990,7 @@
}
public CfCode buildEmptyThrowingCfCode() {
- return buildEmptyThrowingCfCode(method);
+ return buildEmptyThrowingCfCode(getReference());
}
public static CfCode buildEmptyThrowingCfCode(DexMethod method) {
@@ -1034,9 +1026,9 @@
}
instructions[i] = new CfReturn(ValueType.INT);
return new CfCode(
- method.holder,
+ getReference().holder,
1 + BooleanUtils.intValue(negate),
- method.getArity() + 1,
+ getReference().getArity() + 1,
Arrays.asList(instructions),
Collections.emptyList(),
Collections.emptyList());
@@ -1076,10 +1068,13 @@
private DexEncodedMethod toMethodThatLogsErrorDexCode(DexItemFactory itemFactory) {
checkIfObsolete();
- Signature signature = MethodSignature.fromDexMethod(method);
+ Signature signature = MethodSignature.fromDexMethod(getReference());
DexString message =
itemFactory.createString(
- CONFIGURATION_DEBUGGING_PREFIX + method.holder.toSourceString() + ": " + signature);
+ CONFIGURATION_DEBUGGING_PREFIX
+ + getReference().holder.toSourceString()
+ + ": "
+ + signature);
DexString tag = itemFactory.createString("[R8]");
DexType[] args = {itemFactory.stringType, itemFactory.stringType};
DexProto proto = itemFactory.createProto(itemFactory.intType, args);
@@ -1110,10 +1105,13 @@
private DexEncodedMethod toMethodThatLogsErrorCfCode(DexItemFactory itemFactory) {
checkIfObsolete();
- Signature signature = MethodSignature.fromDexMethod(method);
+ Signature signature = MethodSignature.fromDexMethod(getReference());
DexString message =
itemFactory.createString(
- CONFIGURATION_DEBUGGING_PREFIX + method.holder.toSourceString() + ": " + signature);
+ CONFIGURATION_DEBUGGING_PREFIX
+ + getReference().holder.toSourceString()
+ + ": "
+ + signature);
DexString tag = itemFactory.createString("[R8]");
DexType logger = itemFactory.javaUtilLoggingLoggerType;
DexMethod getLogger =
@@ -1132,7 +1130,7 @@
exceptionType,
itemFactory.createProto(itemFactory.voidType, itemFactory.stringType),
itemFactory.constructorMethodName);
- int locals = method.proto.parameters.size() + 1;
+ int locals = getReference().proto.parameters.size() + 1;
if (!isStaticMember()) {
// Consider `this` pointer
locals++;
@@ -1152,7 +1150,7 @@
.add(new CfThrow());
CfCode code =
new CfCode(
- method.holder,
+ getReference().holder,
3,
locals,
instructionBuilder.build(),
@@ -1171,7 +1169,7 @@
public DexEncodedMethod toTypeSubstitutedMethod(DexMethod method, Consumer<Builder> consumer) {
checkIfObsolete();
- if (this.method == method) {
+ if (this.getReference() == method) {
return this;
}
Builder builder = builder(this);
@@ -1243,7 +1241,7 @@
public DexEncodedMethod toRenamedHolderMethod(DexType newHolderType, DexItemFactory factory) {
DexEncodedMethod.Builder builder = DexEncodedMethod.builder(this);
- builder.setMethod(method.withHolder(newHolderType, factory));
+ builder.setMethod(getReference().withHolder(newHolderType, factory));
return builder.build();
}
@@ -1318,7 +1316,7 @@
public DexEncodedMethod toForwardingMethod(
DexClass newHolder, DexDefinitionSupplier definitions) {
- DexMethod newMethod = method.withHolder(newHolder, definitions.dexItemFactory());
+ DexMethod newMethod = getReference().withHolder(newHolder, definitions.dexItemFactory());
checkIfObsolete();
// Clear the final flag, as this method is now overwritten. Do this before creating the builder
@@ -1347,13 +1345,17 @@
.setStaticSource(newMethod)
.setStaticTarget(
getReference(),
- method.getHolderType().isInterface(definitions)),
+ getReference()
+ .getHolderType()
+ .isInterface(definitions)),
codeBuilder ->
codeBuilder
.setNonStaticSource(newMethod)
.setSuperTarget(
getReference(),
- method.getHolderType().isInterface(definitions)))
+ getReference()
+ .getHolderType()
+ .isInterface(definitions)))
.build())
.modifyAccessFlags(MethodAccessFlags::setBridge))
.build();
@@ -1435,7 +1437,7 @@
}
public MethodPosition getPosition() {
- return new MethodPosition(method.asMethodReference());
+ return new MethodPosition(getReference().asMethodReference());
}
@Override
@@ -1456,7 +1458,7 @@
}
public static int slowCompare(DexEncodedMethod m1, DexEncodedMethod m2) {
- return m1.method.compareTo(m2.method);
+ return m1.getReference().compareTo(m2.getReference());
}
public MethodOptimizationInfo getOptimizationInfo() {
@@ -1543,7 +1545,7 @@
private Builder(DexEncodedMethod from, boolean d8R8Synthesized) {
// Copy all the mutable state of a DexEncodedMethod here.
- method = from.method;
+ method = from.getReference();
accessFlags = from.accessFlags.copy();
genericSignature = from.getGenericSignature();
annotations = from.annotations();
diff --git a/src/main/java/com/android/tools/r8/graph/DexField.java b/src/main/java/com/android/tools/r8/graph/DexField.java
index ef99d01..fd2c110 100644
--- a/src/main/java/com/android/tools/r8/graph/DexField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexField.java
@@ -175,7 +175,7 @@
@Override
public boolean match(DexEncodedField encodedField) {
- return match(encodedField.field);
+ return match(encodedField.getReference());
}
public String qualifiedName() {
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 2ce742a..8ba291b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -64,6 +64,8 @@
public static final String throwableDescriptorString = "Ljava/lang/Throwable;";
public static final String dalvikAnnotationSignatureString = "Ldalvik/annotation/Signature;";
+ public static final String recordTagDescriptorString = "Lcom/android/tools/r8/RecordTag;";
+ public static final String recordDescriptorString = "Ljava/lang/Record;";
/** Set of types that may be synthesized during compilation. */
private final Set<DexType> possibleCompilerSynthesizedTypes = Sets.newIdentityHashSet();
@@ -215,8 +217,8 @@
public final DexString stringDescriptor = createString("Ljava/lang/String;");
public final DexString stringArrayDescriptor = createString("[Ljava/lang/String;");
public final DexString objectDescriptor = createString("Ljava/lang/Object;");
- public final DexString recordDescriptor = createString("Ljava/lang/Record;");
- public final DexString r8RecordDescriptor = createString("Lcom/android/tools/r8/RecordTag;");
+ public final DexString recordDescriptor = createString(recordDescriptorString);
+ public final DexString recordTagDescriptor = createString(recordTagDescriptorString);
public final DexString objectArrayDescriptor = createString("[Ljava/lang/Object;");
public final DexString classDescriptor = createString("Ljava/lang/Class;");
public final DexString classLoaderDescriptor = createString("Ljava/lang/ClassLoader;");
@@ -348,7 +350,7 @@
public final DexType stringArrayType = createStaticallyKnownType(stringArrayDescriptor);
public final DexType objectType = createStaticallyKnownType(objectDescriptor);
public final DexType recordType = createStaticallyKnownType(recordDescriptor);
- public final DexType r8RecordType = createStaticallyKnownType(r8RecordDescriptor);
+ public final DexType recordTagType = createStaticallyKnownType(recordTagDescriptor);
public final DexType objectArrayType = createStaticallyKnownType(objectArrayDescriptor);
public final DexType classArrayType = createStaticallyKnownType(classArrayDescriptor);
public final DexType enumType = createStaticallyKnownType(enumDescriptor);
@@ -631,6 +633,10 @@
public final DexType callSiteType = createStaticallyKnownType("Ljava/lang/invoke/CallSite;");
public final DexType lookupType =
createStaticallyKnownType("Ljava/lang/invoke/MethodHandles$Lookup;");
+ public final DexType objectMethodsType =
+ createStaticallyKnownType("Ljava/lang/runtime/ObjectMethods;");
+ public final DexType typeDescriptorType =
+ createStaticallyKnownType("Ljava/lang/invoke/TypeDescriptor;");
public final DexType iteratorType = createStaticallyKnownType("Ljava/util/Iterator;");
public final DexType listIteratorType = createStaticallyKnownType("Ljava/util/ListIterator;");
public final DexType enumerationType = createStaticallyKnownType("Ljava/util/Enumeration;");
@@ -642,6 +648,7 @@
createStaticallyKnownType("Ljava/lang/invoke/StringConcatFactory;");
public final DexType unsafeType = createStaticallyKnownType("Lsun/misc/Unsafe;");
+ public final ObjectMethodsMembers objectMethodsMembers = new ObjectMethodsMembers();
public final ServiceLoaderMethods serviceLoaderMethods = new ServiceLoaderMethods();
public final StringConcatFactoryMembers stringConcatFactoryMembers =
new StringConcatFactoryMembers();
@@ -1215,6 +1222,21 @@
public final DexMethod toString = createMethod(recordType, createProto(stringType), "toString");
}
+ public class ObjectMethodsMembers {
+ public final DexMethod bootstrap =
+ createMethod(
+ objectMethodsType,
+ createProto(
+ objectType,
+ lookupType,
+ stringType,
+ typeDescriptorType,
+ classType,
+ stringType,
+ createArrayType(1, methodHandleType)),
+ "bootstrap");
+ }
+
public class ObjectMembers {
/**
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 8484a94..c96dc4a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -223,7 +223,7 @@
@Override
public boolean match(DexEncodedMethod encodedMethod) {
- return match(encodedMethod.method);
+ return match(encodedMethod.getReference());
}
public String qualifiedName() {
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index a4ccb8e..881b0e9 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -559,7 +559,8 @@
return null;
}
DexEncodedField[] fields = staticFields;
- Arrays.sort(fields, (a, b) -> a.field.compareToWithNamingLens(b.field, namingLens));
+ Arrays.sort(
+ fields, (a, b) -> a.getReference().compareToWithNamingLens(b.getReference(), namingLens));
int length = 0;
List<DexValue> values = new ArrayList<>(fields.length);
for (int i = 0; i < fields.length; i++) {
@@ -567,7 +568,7 @@
DexValue staticValue = field.getStaticValue();
assert staticValue != null;
values.add(staticValue);
- if (!staticValue.isDefault(field.field.type)) {
+ if (!staticValue.isDefault(field.getReference().type)) {
length = i + 1;
}
}
@@ -579,7 +580,7 @@
private boolean hasNonDefaultStaticFieldValues() {
for (DexEncodedField field : staticFields) {
DexValue value = field.getStaticValue();
- if (value != null && !value.isDefault(field.field.type)) {
+ if (value != null && !value.isDefault(field.getReference().type)) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 75b592b..a38770a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -315,6 +315,14 @@
return isDoubleType() || isLongType();
}
+ public boolean isSynthesizedTypeAllowedDuplication() {
+ // If we are desugaring Records, then the r8Record type is mapped back to java.lang.Record, and
+ // java.lang.Record can be duplicated.
+ // If we are not desugaring Records, then the r8Record type can be duplicated instead.
+ return descriptor.toString().equals(DexItemFactory.recordDescriptorString)
+ || descriptor.toString().equals(DexItemFactory.recordTagDescriptorString);
+ }
+
public boolean isLegacySynthesizedTypeAllowedDuplication() {
return oldSynthesizedName(toSourceString());
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignature.java b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
index 1dc1f4f..2fa08c8 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignature.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
@@ -542,6 +542,15 @@
visitor.visitSimpleClass(innerTypeSignature);
}
}
+
+ public boolean hasTypeVariableArguments() {
+ for (FieldTypeSignature typeArgument : typeArguments) {
+ if (typeArgument.isTypeVariableSignature()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
public static class ArrayTypeSignature extends FieldTypeSignature {
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index 7135cfc..610208f 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -13,12 +13,9 @@
import com.android.tools.r8.utils.Action;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.SetUtils;
-import com.android.tools.r8.utils.collections.BidirectionalManyToManyRepresentativeMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
-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.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -33,7 +30,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
/**
* A GraphLens implements a virtual view on top of the graph, used to delay global rewrites until
@@ -233,18 +229,16 @@
}
}
- public static class Builder {
+ public abstract static class Builder {
+
+ protected final MutableBidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap =
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
+ protected final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap =
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
+ protected final Map<DexType, DexType> typeMap = new IdentityHashMap<>();
protected Builder() {}
- protected final Map<DexType, DexType> typeMap = new IdentityHashMap<>();
- protected final Map<DexMethod, DexMethod> methodMap = new IdentityHashMap<>();
- protected final MutableBidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap =
- new BidirectionalManyToOneRepresentativeHashMap<>();
-
- protected final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures =
- new BidirectionalOneToOneHashMap<>();
-
public void map(DexType from, DexType to) {
if (from == to) {
return;
@@ -252,19 +246,11 @@
typeMap.put(from, to);
}
- public void map(DexMethod from, DexMethod to) {
- if (from == to) {
- return;
- }
- methodMap.put(from, to);
- }
-
public void move(DexMethod from, DexMethod to) {
if (from == to) {
return;
}
- map(from, to);
- originalMethodSignatures.put(to, from);
+ methodMap.put(from, to);
}
public void move(DexField from, DexField to) {
@@ -274,22 +260,7 @@
fieldMap.put(from, to);
}
- public GraphLens build(DexItemFactory dexItemFactory) {
- return build(dexItemFactory, getIdentityLens());
- }
-
- public GraphLens build(DexItemFactory dexItemFactory, GraphLens previousLens) {
- if (typeMap.isEmpty() && methodMap.isEmpty() && fieldMap.isEmpty()) {
- return previousLens;
- }
- return new NestedGraphLens(
- typeMap,
- methodMap,
- fieldMap,
- originalMethodSignatures,
- previousLens,
- dexItemFactory);
- }
+ public abstract GraphLens build(AppView<?> appView);
}
/**
@@ -334,7 +305,7 @@
DexDefinitionSupplier definitions,
GraphLens applied) {
assert originalEncodedMethod != DexEncodedMethod.SENTINEL;
- DexMethod newMethod = getRenamedMethodSignature(originalEncodedMethod.method, applied);
+ DexMethod newMethod = getRenamedMethodSignature(originalEncodedMethod.getReference(), applied);
// Note that:
// * Even if `newMethod` is the same as `originalEncodedMethod.method`, we still need to look it
// up, since `originalEncodedMethod` may be obsolete.
@@ -602,10 +573,10 @@
Set<DexMethod> originalMethods = Sets.newIdentityHashSet();
for (DexProgramClass clazz : originalApplication.classes()) {
for (DexEncodedField field : clazz.fields()) {
- originalFields.add(field.field);
+ originalFields.add(field.getReference());
}
for (DexEncodedMethod method : clazz.methods()) {
- originalMethods.add(method.method);
+ originalMethods.add(method.getReference());
}
}
@@ -631,7 +602,7 @@
// Methods synthesized by D8/R8 may not be mapped.
continue;
}
- DexMethod originalMethod = getOriginalMethodSignature(method.method);
+ DexMethod originalMethod = getOriginalMethodSignature(method.getReference());
assert originalMethods.contains(originalMethod);
}
}
@@ -959,288 +930,4 @@
return getIdentityLens().isContextFreeForMethods();
}
}
-
- /**
- * GraphLens implementation with a parent lens using a simple mapping for type, method and field
- * mapping.
- *
- * <p>Subclasses can override the lookup methods.
- *
- * <p>For method mapping where invocation type can change just override {@link
- * #mapInvocationType(DexMethod, DexMethod, Type)} if the default name mapping applies, and only
- * invocation type might need to change.
- */
- public static class NestedGraphLens extends NonIdentityGraphLens {
-
- protected final DexItemFactory dexItemFactory;
-
- protected final Map<DexType, DexType> typeMap;
- protected final Map<DexMethod, DexMethod> methodMap;
- protected final BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap;
-
- // Map that store the original signature of methods that have been affected, for example, by
- // vertical class merging. Needed to generate a correct Proguard map in the end.
- protected BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod>
- originalMethodSignatures;
-
- // Overrides this if the sub type needs to be a nested lens while it doesn't have any mappings
- // at all, e.g., publicizer lens that changes invocation type only.
- protected boolean isLegitimateToHaveEmptyMappings() {
- return false;
- }
-
- public NestedGraphLens(
- Map<DexType, DexType> typeMap,
- Map<DexMethod, DexMethod> methodMap,
- BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
- BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> originalMethodSignatures,
- GraphLens previousLens,
- DexItemFactory dexItemFactory) {
- super(dexItemFactory, previousLens);
- assert !typeMap.isEmpty()
- || !methodMap.isEmpty()
- || !fieldMap.isEmpty()
- || isLegitimateToHaveEmptyMappings();
- this.typeMap = typeMap.isEmpty() ? null : typeMap;
- this.methodMap = methodMap;
- this.fieldMap = fieldMap;
- this.originalMethodSignatures = originalMethodSignatures;
- this.dexItemFactory = dexItemFactory;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- protected DexType internalGetOriginalType(DexType previous) {
- return previous;
- }
-
- protected Iterable<DexType> internalGetOriginalTypes(DexType previous) {
- return IterableUtils.singleton(internalGetOriginalType(previous));
- }
-
- @Override
- public DexType getOriginalType(DexType type) {
- return getPrevious().getOriginalType(internalGetOriginalType(type));
- }
-
- @Override
- public Iterable<DexType> getOriginalTypes(DexType type) {
- return IterableUtils.flatMap(internalGetOriginalTypes(type), getPrevious()::getOriginalTypes);
- }
-
- @Override
- public DexField getOriginalFieldSignature(DexField field) {
- DexField originalField = fieldMap.getRepresentativeKeyOrDefault(field, field);
- return getPrevious().getOriginalFieldSignature(originalField);
- }
-
- @Override
- public DexMethod getOriginalMethodSignature(DexMethod method) {
- DexMethod originalMethod = internalGetPreviousMethodSignature(method);
- return getPrevious().getOriginalMethodSignature(originalMethod);
- }
-
- @Override
- public DexField getRenamedFieldSignature(DexField originalField) {
- DexField renamedField = getPrevious().getRenamedFieldSignature(originalField);
- return internalGetNextFieldSignature(renamedField);
- }
-
- @Override
- public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
- if (this == applied) {
- return originalMethod;
- }
- DexMethod renamedMethod = getPrevious().getRenamedMethodSignature(originalMethod, applied);
- return internalGetNextMethodSignature(renamedMethod);
- }
-
- @Override
- protected DexType internalDescribeLookupClassType(DexType previous) {
- return typeMap != null ? typeMap.getOrDefault(previous, previous) : previous;
- }
-
- @Override
- protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
- if (previous.hasReboundReference()) {
- // Rewrite the rebound reference and then "fixup" the non-rebound reference.
- DexField rewrittenReboundReference = previous.getRewrittenReboundReference(fieldMap);
- DexField rewrittenNonReboundReference =
- previous.getReference() == previous.getReboundReference()
- ? rewrittenReboundReference
- : rewrittenReboundReference.withHolder(
- internalDescribeLookupClassType(previous.getReference().getHolderType()),
- dexItemFactory);
- return FieldLookupResult.builder(this)
- .setReboundReference(rewrittenReboundReference)
- .setReference(rewrittenNonReboundReference)
- .setCastType(previous.getRewrittenCastType(this::internalDescribeLookupClassType))
- .build();
- } else {
- // TODO(b/168282032): We should always have the rebound reference, so this should become
- // unreachable.
- DexField rewrittenReference = previous.getRewrittenReference(fieldMap);
- return FieldLookupResult.builder(this)
- .setReference(rewrittenReference)
- .setCastType(previous.getRewrittenCastType(this::internalDescribeLookupClassType))
- .build();
- }
- }
-
- @Override
- public MethodLookupResult internalDescribeLookupMethod(
- MethodLookupResult previous, DexMethod context) {
- if (previous.hasReboundReference()) {
- // TODO(sgjesse): Should we always do interface to virtual mapping? Is it a performance win
- // that only subclasses which are known to need it actually do it?
- DexMethod rewrittenReboundReference = previous.getRewrittenReboundReference(methodMap);
- DexMethod rewrittenReference =
- previous.getReference() == previous.getReboundReference()
- ? rewrittenReboundReference
- : // This assumes that the holder will always be moved in lock-step with the method!
- rewrittenReboundReference.withHolder(
- internalDescribeLookupClassType(previous.getReference().getHolderType()),
- dexItemFactory);
- return MethodLookupResult.builder(this)
- .setReference(rewrittenReference)
- .setReboundReference(rewrittenReboundReference)
- .setPrototypeChanges(
- internalDescribePrototypeChanges(
- previous.getPrototypeChanges(), rewrittenReboundReference))
- .setType(
- mapInvocationType(
- rewrittenReboundReference, previous.getReference(), previous.getType()))
- .build();
- } else {
- // TODO(b/168282032): We should always have the rebound reference, so this should become
- // unreachable.
- DexMethod newMethod = methodMap.get(previous.getReference());
- if (newMethod == null) {
- return previous;
- }
- // TODO(sgjesse): Should we always do interface to virtual mapping? Is it a performance win
- // that only subclasses which are known to need it actually do it?
- return MethodLookupResult.builder(this)
- .setReference(newMethod)
- .setPrototypeChanges(
- internalDescribePrototypeChanges(previous.getPrototypeChanges(), newMethod))
- .setType(mapInvocationType(newMethod, previous.getReference(), previous.getType()))
- .build();
- }
- }
-
- @Override
- public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
- DexMethod method) {
- DexMethod previous = internalGetPreviousMethodSignature(method);
- RewrittenPrototypeDescription lookup =
- getPrevious().lookupPrototypeChangesForMethodDefinition(previous);
- return internalDescribePrototypeChanges(lookup, method);
- }
-
- protected RewrittenPrototypeDescription internalDescribePrototypeChanges(
- RewrittenPrototypeDescription prototypeChanges, DexMethod method) {
- return prototypeChanges;
- }
-
- protected DexField internalGetNextFieldSignature(DexField field) {
- return fieldMap.getOrDefault(field, field);
- }
-
- @Override
- protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
- return originalMethodSignatures.getRepresentativeValueOrDefault(method, method);
- }
-
- protected DexMethod internalGetNextMethodSignature(DexMethod method) {
- return originalMethodSignatures.getRepresentativeKeyOrDefault(method, method);
- }
-
- @Override
- public DexMethod lookupGetFieldForMethod(DexField field, DexMethod context) {
- return getPrevious().lookupGetFieldForMethod(field, context);
- }
-
- @Override
- public DexMethod lookupPutFieldForMethod(DexField field, DexMethod context) {
- return getPrevious().lookupPutFieldForMethod(field, context);
- }
-
- /**
- * Default invocation type mapping.
- *
- * <p>This is an identity mapping. If a subclass need invocation type mapping either override
- * this method or {@link #lookupMethod(DexMethod, DexMethod, Type)}
- */
- protected Type mapInvocationType(DexMethod newMethod, DexMethod originalMethod, Type type) {
- return type;
- }
-
- /**
- * Standard mapping between interface and virtual invoke type.
- *
- * <p>Handle methods moved from interface to class or class to interface.
- */
- public static Type mapVirtualInterfaceInvocationTypes(
- DexDefinitionSupplier definitions,
- DexMethod newMethod,
- DexMethod originalMethod,
- Type type) {
- if (type == Type.VIRTUAL || type == Type.INTERFACE) {
- // Get the invoke type of the actual definition.
- DexClass newTargetClass = definitions.definitionFor(newMethod.getHolderType());
- if (newTargetClass == null) {
- return type;
- }
- DexClass originalTargetClass = definitions.definitionFor(originalMethod.getHolderType());
- if (originalTargetClass != null
- && (originalTargetClass.isInterface() ^ (type == Type.INTERFACE))) {
- // The invoke was wrong to start with, so we keep it wrong. This is to ensure we get
- // the IncompatibleClassChangeError the original invoke would have triggered.
- return newTargetClass.accessFlags.isInterface() ? Type.VIRTUAL : Type.INTERFACE;
- }
- return newTargetClass.accessFlags.isInterface() ? Type.INTERFACE : Type.VIRTUAL;
- }
- return type;
- }
-
- @Override
- public boolean isContextFreeForMethods() {
- return getPrevious().isContextFreeForMethods();
- }
-
- @Override
- public boolean verifyIsContextFreeForMethod(DexMethod method) {
- assert getPrevious().verifyIsContextFreeForMethod(method);
- return true;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- if (typeMap != null) {
- for (Map.Entry<DexType, DexType> entry : typeMap.entrySet()) {
- builder.append(entry.getKey().toSourceString()).append(" -> ");
- builder.append(entry.getValue().toSourceString()).append(System.lineSeparator());
- }
- }
- for (Map.Entry<DexMethod, DexMethod> entry : methodMap.entrySet()) {
- builder.append(entry.getKey().toSourceString()).append(" -> ");
- builder.append(entry.getValue().toSourceString()).append(System.lineSeparator());
- }
- fieldMap.forEachManyToOneMapping(
- (keys, value) -> {
- builder.append(
- keys.stream()
- .map(DexField::toSourceString)
- .collect(Collectors.joining("," + System.lineSeparator())));
- builder.append(" -> ");
- builder.append(value.toSourceString()).append(System.lineSeparator());
- });
- builder.append(getPrevious().toString());
- return builder.toString();
- }
- }
}
diff --git a/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java b/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
index 8b5977f..67e7b5b 100644
--- a/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.objectweb.asm.Type;
@@ -23,9 +24,11 @@
private final ConcurrentHashMap<String, Type> asmObjectTypeCache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Type> asmTypeCache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, DexString> stringCache = new ConcurrentHashMap<>();
+ private final Map<String, String> typeDescriptorMap;
public JarApplicationReader(InternalOptions options) {
this.options = options;
+ typeDescriptorMap = ApplicationReaderMap.getDescriptorMap(options);
}
public Type getAsmObjectType(String name) {
@@ -55,7 +58,8 @@
public DexType getTypeFromDescriptor(String desc) {
assert isValidDescriptor(desc);
- return options.itemFactory.createType(getString(desc));
+ String actualDesc = typeDescriptorMap.getOrDefault(desc, desc);
+ return options.itemFactory.createType(getString(actualDesc));
}
public DexTypeList getTypeListFromNames(String[] names) {
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index d8815c7..4def125 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -510,9 +510,9 @@
throw new CompilationError(message, origin);
}
for (DexEncodedField instanceField : instanceFields) {
- if (!recordComponents.contains(instanceField.field)) {
+ if (!recordComponents.contains(instanceField.getReference())) {
throw new CompilationError(
- message + " Unmatched field " + instanceField.field + ".", origin);
+ message + " Unmatched field " + instanceField.getReference() + ".", origin);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/LookupCompletenessHelper.java b/src/main/java/com/android/tools/r8/graph/LookupCompletenessHelper.java
index 3c7b2d8..4a99071 100644
--- a/src/main/java/com/android/tools/r8/graph/LookupCompletenessHelper.java
+++ b/src/main/java/com/android/tools/r8/graph/LookupCompletenessHelper.java
@@ -34,7 +34,7 @@
if (pinnedMethods == null) {
pinnedMethods = Sets.newIdentityHashSet();
}
- pinnedMethods.add(method.method);
+ pinnedMethods.add(method.getReference());
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
index 7c38464..17072ef 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -26,8 +26,8 @@
Set<DexMethod> unique = Sets.newIdentityHashSet();
forEachMethod(
method -> {
- boolean changed = unique.add(method.method);
- assert changed : "Duplicate method `" + method.method.toSourceString() + "`";
+ boolean changed = unique.add(method.getReference());
+ assert changed : "Duplicate method `" + method.getReference().toSourceString() + "`";
});
return true;
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollection.java b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
index ccf33aa..35e0541 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -137,7 +137,7 @@
public List<DexEncodedMethod> allMethodsSorted() {
List<DexEncodedMethod> sorted = new ArrayList<>(size());
forEachMethod(sorted::add);
- sorted.sort((a, b) -> a.method.compareTo(b.method));
+ sorted.sort((a, b) -> a.getReference().compareTo(b.getReference()));
return sorted;
}
@@ -344,7 +344,7 @@
private boolean verifyCorrectnessOfMethodHolder(DexEncodedMethod method) {
assert method.getHolderType() == holder.type
: "Expected method `"
- + method.method.toSourceString()
+ + method.getReference().toSourceString()
+ "` to have holder `"
+ holder.type.toSourceString()
+ "`";
diff --git a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
index f3385af..a7d3c45 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
@@ -57,7 +57,7 @@
methodMap.put(existingKey, method);
} else {
methodMap.remove(existingKey);
- methodMap.put(wrap(method.method), method);
+ methodMap.put(wrap(method.getReference()), method);
}
}
@@ -165,7 +165,7 @@
@Override
void addMethod(DexEncodedMethod method) {
- Wrapper<DexMethod> key = wrap(method.method);
+ Wrapper<DexMethod> key = wrap(method.getReference());
DexEncodedMethod old = methodMap.put(key, method);
assert old == null;
}
@@ -229,12 +229,12 @@
forEachMethod(
method -> {
if (belongsToVirtualPool(method)) {
- newMap.put(wrap(method.method), method);
+ newMap.put(wrap(method.getReference()), method);
}
});
for (DexEncodedMethod method : methods) {
assert belongsToDirectPool(method);
- newMap.put(wrap(method.method), method);
+ newMap.put(wrap(method.getReference()), method);
}
methodMap = newMap;
}
@@ -252,12 +252,12 @@
forEachMethod(
method -> {
if (belongsToDirectPool(method)) {
- newMap.put(wrap(method.method), method);
+ newMap.put(wrap(method.getReference()), method);
}
});
for (DexEncodedMethod method : methods) {
assert belongsToVirtualPool(method);
- newMap.put(wrap(method.method), method);
+ newMap.put(wrap(method.getReference()), method);
}
methodMap = newMap;
}
@@ -271,7 +271,7 @@
for (DexEncodedMethod method : initialValues) {
DexEncodedMethod newMethod = replacement.apply(method);
if (newMethod != method) {
- removeMethod(method.method);
+ removeMethod(method.getReference());
addMethod(newMethod);
}
}
@@ -359,7 +359,7 @@
private boolean verifyVirtualizedMethods(Set<DexEncodedMethod> methods) {
for (DexEncodedMethod method : methods) {
assert belongsToVirtualPool(method);
- assert methodMap.get(wrap(method.method)) == method;
+ assert methodMap.get(wrap(method.getReference())) == method;
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/graph/NestedGraphLens.java b/src/main/java/com/android/tools/r8/graph/NestedGraphLens.java
new file mode 100644
index 0000000..8eaa46f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/NestedGraphLens.java
@@ -0,0 +1,320 @@
+// 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.graph;
+
+import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.ir.code.Invoke.Type;
+import com.android.tools.r8.utils.IterableUtils;
+import com.android.tools.r8.utils.collections.BidirectionalManyToManyRepresentativeMap;
+import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
+import com.android.tools.r8.utils.collections.EmptyBidirectionalOneToOneMap;
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * GraphLens implementation with a parent lens using a simple mapping for type, method and field
+ * mapping.
+ *
+ * <p>Subclasses can override the lookup methods.
+ *
+ * <p>For method mapping where invocation type can change just override {@link
+ * #mapInvocationType(DexMethod, DexMethod, Type)} if the default name mapping applies, and only
+ * invocation type might need to change.
+ */
+public class NestedGraphLens extends NonIdentityGraphLens {
+
+ protected static final EmptyBidirectionalOneToOneMap<DexField, DexField> EMPTY_FIELD_MAP =
+ new EmptyBidirectionalOneToOneMap<>();
+ protected static final EmptyBidirectionalOneToOneMap<DexMethod, DexMethod> EMPTY_METHOD_MAP =
+ new EmptyBidirectionalOneToOneMap<>();
+ protected static final Map<DexType, DexType> EMPTY_TYPE_MAP = Collections.emptyMap();
+
+ protected final BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap;
+ protected final Map<DexMethod, DexMethod> methodMap;
+ protected final Map<DexType, DexType> typeMap;
+
+ // Map that stores the new signature of methods that have been affected by class merging, unused
+ // argument removal, repackaging, synthetic finalization, etc. This is needed to generate a
+ // correct mapping file in the end.
+ //
+ // The difference to `methodMap` is that `methodMap` specifies how invoke-method instructions
+ // should be rewritten, whereas this map specifies where methods have been moved. In most cases
+ // the two maps are the same, but in a few cases we move a method m1 to m2 and rewrite invokes to
+ // m1 to m3.
+ //
+ // The static type of this map is a many-to-many map to facilitate both one-to-many mappings and
+ // many-to-one mappings. Currently, the concrete map is always *either* a one-to-many or a
+ // many-to-one map, and not a many-to-many map.
+ //
+ // One-to-many mappings are generally found when methods are split into two. This could be due to
+ // the code object being moved elsewhere (e.g., interface desugaring).
+ //
+ // Many-to-one mappings are generally found when methods are shared, e.g., due to horizontal class
+ // merging of synthetic finalization.
+ protected BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> newMethodSignatures;
+
+ // Overrides this if the sub type needs to be a nested lens while it doesn't have any mappings
+ // at all, e.g., publicizer lens that changes invocation type only.
+ protected boolean isLegitimateToHaveEmptyMappings() {
+ return false;
+ }
+
+ public NestedGraphLens(
+ AppView<?> appView,
+ BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
+ BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap,
+ Map<DexType, DexType> typeMap) {
+ this(appView, fieldMap, methodMap.getForwardMap(), typeMap, methodMap);
+ }
+
+ public NestedGraphLens(
+ AppView<?> appView,
+ BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
+ Map<DexMethod, DexMethod> methodMap,
+ Map<DexType, DexType> typeMap,
+ BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> newMethodSignatures) {
+ super(appView);
+ assert !typeMap.isEmpty()
+ || !methodMap.isEmpty()
+ || !fieldMap.isEmpty()
+ || isLegitimateToHaveEmptyMappings();
+ this.fieldMap = fieldMap;
+ this.methodMap = methodMap;
+ this.typeMap = typeMap;
+ this.newMethodSignatures = newMethodSignatures;
+ }
+
+ protected DexType internalGetOriginalType(DexType previous) {
+ return previous;
+ }
+
+ protected Iterable<DexType> internalGetOriginalTypes(DexType previous) {
+ return IterableUtils.singleton(internalGetOriginalType(previous));
+ }
+
+ @Override
+ public DexType getOriginalType(DexType type) {
+ return getPrevious().getOriginalType(internalGetOriginalType(type));
+ }
+
+ @Override
+ public Iterable<DexType> getOriginalTypes(DexType type) {
+ return IterableUtils.flatMap(internalGetOriginalTypes(type), getPrevious()::getOriginalTypes);
+ }
+
+ @Override
+ public DexField getOriginalFieldSignature(DexField field) {
+ DexField originalField = fieldMap.getRepresentativeKeyOrDefault(field, field);
+ return getPrevious().getOriginalFieldSignature(originalField);
+ }
+
+ @Override
+ public DexMethod getOriginalMethodSignature(DexMethod method) {
+ DexMethod originalMethod = internalGetPreviousMethodSignature(method);
+ return getPrevious().getOriginalMethodSignature(originalMethod);
+ }
+
+ @Override
+ public DexField getRenamedFieldSignature(DexField originalField) {
+ DexField renamedField = getPrevious().getRenamedFieldSignature(originalField);
+ return internalGetNextFieldSignature(renamedField);
+ }
+
+ @Override
+ public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
+ if (this == applied) {
+ return originalMethod;
+ }
+ DexMethod renamedMethod = getPrevious().getRenamedMethodSignature(originalMethod, applied);
+ return internalGetNextMethodSignature(renamedMethod);
+ }
+
+ @Override
+ protected DexType internalDescribeLookupClassType(DexType previous) {
+ return typeMap.getOrDefault(previous, previous);
+ }
+
+ @Override
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ if (previous.hasReboundReference()) {
+ // Rewrite the rebound reference and then "fixup" the non-rebound reference.
+ DexField rewrittenReboundReference = previous.getRewrittenReboundReference(fieldMap);
+ DexField rewrittenNonReboundReference =
+ previous.getReference() == previous.getReboundReference()
+ ? rewrittenReboundReference
+ : rewrittenReboundReference.withHolder(
+ internalDescribeLookupClassType(previous.getReference().getHolderType()),
+ dexItemFactory());
+ return FieldLookupResult.builder(this)
+ .setReboundReference(rewrittenReboundReference)
+ .setReference(rewrittenNonReboundReference)
+ .setCastType(previous.getRewrittenCastType(this::internalDescribeLookupClassType))
+ .build();
+ } else {
+ // TODO(b/168282032): We should always have the rebound reference, so this should become
+ // unreachable.
+ DexField rewrittenReference = previous.getRewrittenReference(fieldMap);
+ return FieldLookupResult.builder(this)
+ .setReference(rewrittenReference)
+ .setCastType(previous.getRewrittenCastType(this::internalDescribeLookupClassType))
+ .build();
+ }
+ }
+
+ @Override
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ if (previous.hasReboundReference()) {
+ // TODO(sgjesse): Should we always do interface to virtual mapping? Is it a performance win
+ // that only subclasses which are known to need it actually do it?
+ DexMethod rewrittenReboundReference = previous.getRewrittenReboundReference(methodMap);
+ DexMethod rewrittenReference =
+ previous.getReference() == previous.getReboundReference()
+ ? rewrittenReboundReference
+ : // This assumes that the holder will always be moved in lock-step with the method!
+ rewrittenReboundReference.withHolder(
+ internalDescribeLookupClassType(previous.getReference().getHolderType()),
+ dexItemFactory());
+ return MethodLookupResult.builder(this)
+ .setReference(rewrittenReference)
+ .setReboundReference(rewrittenReboundReference)
+ .setPrototypeChanges(
+ internalDescribePrototypeChanges(
+ previous.getPrototypeChanges(), rewrittenReboundReference))
+ .setType(
+ mapInvocationType(
+ rewrittenReboundReference, previous.getReference(), previous.getType()))
+ .build();
+ } else {
+ // TODO(b/168282032): We should always have the rebound reference, so this should become
+ // unreachable.
+ DexMethod newMethod = methodMap.get(previous.getReference());
+ if (newMethod == null) {
+ return previous;
+ }
+ // TODO(sgjesse): Should we always do interface to virtual mapping? Is it a performance win
+ // that only subclasses which are known to need it actually do it?
+ return MethodLookupResult.builder(this)
+ .setReference(newMethod)
+ .setPrototypeChanges(
+ internalDescribePrototypeChanges(previous.getPrototypeChanges(), newMethod))
+ .setType(mapInvocationType(newMethod, previous.getReference(), previous.getType()))
+ .build();
+ }
+ }
+
+ @Override
+ public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(DexMethod method) {
+ DexMethod previous = internalGetPreviousMethodSignature(method);
+ RewrittenPrototypeDescription lookup =
+ getPrevious().lookupPrototypeChangesForMethodDefinition(previous);
+ return internalDescribePrototypeChanges(lookup, method);
+ }
+
+ protected RewrittenPrototypeDescription internalDescribePrototypeChanges(
+ RewrittenPrototypeDescription prototypeChanges, DexMethod method) {
+ return prototypeChanges;
+ }
+
+ protected DexField internalGetNextFieldSignature(DexField field) {
+ return fieldMap.getOrDefault(field, field);
+ }
+
+ @Override
+ protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+ return newMethodSignatures.getRepresentativeKeyOrDefault(method, method);
+ }
+
+ protected DexMethod internalGetNextMethodSignature(DexMethod method) {
+ return newMethodSignatures.getRepresentativeValueOrDefault(method, method);
+ }
+
+ @Override
+ public DexMethod lookupGetFieldForMethod(DexField field, DexMethod context) {
+ return getPrevious().lookupGetFieldForMethod(field, context);
+ }
+
+ @Override
+ public DexMethod lookupPutFieldForMethod(DexField field, DexMethod context) {
+ return getPrevious().lookupPutFieldForMethod(field, context);
+ }
+
+ /**
+ * Default invocation type mapping.
+ *
+ * <p>This is an identity mapping. If a subclass need invocation type mapping either override this
+ * method or {@link #lookupMethod(DexMethod, DexMethod, Type)}
+ */
+ protected Type mapInvocationType(DexMethod newMethod, DexMethod originalMethod, Type type) {
+ return type;
+ }
+
+ /**
+ * Standard mapping between interface and virtual invoke type.
+ *
+ * <p>Handle methods moved from interface to class or class to interface.
+ */
+ public static Type mapVirtualInterfaceInvocationTypes(
+ DexDefinitionSupplier definitions, DexMethod newMethod, DexMethod originalMethod, Type type) {
+ if (type == Type.VIRTUAL || type == Type.INTERFACE) {
+ // Get the invoke type of the actual definition.
+ DexClass newTargetClass = definitions.definitionFor(newMethod.getHolderType());
+ if (newTargetClass == null) {
+ return type;
+ }
+ DexClass originalTargetClass = definitions.definitionFor(originalMethod.getHolderType());
+ if (originalTargetClass != null
+ && (originalTargetClass.isInterface() ^ (type == Type.INTERFACE))) {
+ // The invoke was wrong to start with, so we keep it wrong. This is to ensure we get
+ // the IncompatibleClassChangeError the original invoke would have triggered.
+ return newTargetClass.accessFlags.isInterface() ? Type.VIRTUAL : Type.INTERFACE;
+ }
+ return newTargetClass.accessFlags.isInterface() ? Type.INTERFACE : Type.VIRTUAL;
+ }
+ return type;
+ }
+
+ @Override
+ public boolean isContextFreeForMethods() {
+ return getPrevious().isContextFreeForMethods();
+ }
+
+ @Override
+ public boolean verifyIsContextFreeForMethod(DexMethod method) {
+ assert getPrevious().verifyIsContextFreeForMethod(method);
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ typeMap.forEach(
+ (from, to) ->
+ builder
+ .append(from.getTypeName())
+ .append(" -> ")
+ .append(to.getTypeName())
+ .append(System.lineSeparator()));
+ methodMap.forEach(
+ (from, to) ->
+ builder
+ .append(from.toSourceString())
+ .append(" -> ")
+ .append(to.toSourceString())
+ .append(System.lineSeparator()));
+ fieldMap.forEachManyToOneMapping(
+ (fromSet, to) -> {
+ builder.append(
+ fromSet.stream()
+ .map(DexField::toSourceString)
+ .collect(Collectors.joining("," + System.lineSeparator())));
+ builder.append(" -> ");
+ builder.append(to.toSourceString()).append(System.lineSeparator());
+ });
+ builder.append(getPrevious().toString());
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
index 041033e..e3558a2 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.InstantiatedObject;
+import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.OptionalBool;
import java.util.ArrayList;
@@ -60,6 +61,14 @@
return false;
}
+ public boolean isNoSuchMethodErrorResult(DexClass context, AppInfoWithClassHierarchy appInfo) {
+ return false;
+ }
+
+ public boolean isIllegalAccessErrorResult(DexClass context, AppInfoWithClassHierarchy appInfo) {
+ return false;
+ }
+
/** Returns non-null if isFailedResolution() is true, otherwise null. */
public FailedResolutionResult asFailedResolution() {
return null;
@@ -346,7 +355,7 @@
return null;
}
// 1-3. Search the initial class and its supers in order for a matching instance method.
- DexMethod method = getResolvedMethod().method;
+ DexMethod method = getResolvedMethod().getReference();
DexClassAndMethod target = null;
DexClass current = initialType;
while (current != null) {
@@ -446,7 +455,7 @@
return LookupResult.createResult(
methodTargets,
lambdaTargets,
- incompleteness.computeCollectionState(resolvedMethod.method, appInfo));
+ incompleteness.computeCollectionState(resolvedMethod.getReference(), appInfo));
}
@Override
@@ -626,12 +635,12 @@
private DexClassAndMethod lookupMaximallySpecificDispatchTarget(
DexClass dynamicInstance, AppInfoWithClassHierarchy appInfo) {
- return appInfo.lookupMaximallySpecificMethod(dynamicInstance, resolvedMethod.method);
+ return appInfo.lookupMaximallySpecificMethod(dynamicInstance, resolvedMethod.getReference());
}
private DexClassAndMethod lookupMaximallySpecificDispatchTarget(
LambdaDescriptor lambdaDescriptor, AppInfoWithClassHierarchy appInfo) {
- return appInfo.lookupMaximallySpecificMethod(lambdaDescriptor, resolvedMethod.method);
+ return appInfo.lookupMaximallySpecificMethod(lambdaDescriptor, resolvedMethod.getReference());
}
/**
@@ -642,7 +651,7 @@
*/
private static DexEncodedMethod lookupOverrideCandidate(
DexEncodedMethod method, DexClass clazz) {
- DexEncodedMethod candidate = clazz.lookupVirtualMethod(method.method);
+ DexEncodedMethod candidate = clazz.lookupVirtualMethod(method.getReference());
assert candidate == null || !candidate.isPrivateMethod();
if (candidate != null) {
return isOverriding(method, candidate) ? candidate : DexEncodedMethod.SENTINEL;
@@ -659,7 +668,7 @@
if (clazz == null) {
return resolvedMethod;
}
- DexEncodedMethod otherOverride = clazz.lookupVirtualMethod(resolvedMethod.method);
+ DexEncodedMethod otherOverride = clazz.lookupVirtualMethod(resolvedMethod.getReference());
if (otherOverride != null
&& isOverriding(resolvedMethod, otherOverride)
&& (otherOverride.accessFlags.isPublic() || otherOverride.accessFlags.isProtected())) {
@@ -680,7 +689,7 @@
*/
public static boolean isOverriding(
DexEncodedMethod resolvedMethod, DexEncodedMethod candidate) {
- assert resolvedMethod.method.match(candidate.method);
+ assert resolvedMethod.getReference().match(candidate.getReference());
assert !candidate.isPrivateMethod();
if (resolvedMethod.accessFlags.isPublic() || resolvedMethod.accessFlags.isProtected()) {
return true;
@@ -814,6 +823,10 @@
public boolean isVirtualTarget() {
return false;
}
+
+ public boolean hasMethodsCausingError() {
+ return false;
+ }
}
public static class ClassNotFoundResult extends FailedResolutionResult {
@@ -824,7 +837,7 @@
}
}
- abstract static class FailedResolutionWithCausingMethods extends FailedResolutionResult {
+ public abstract static class FailedResolutionWithCausingMethods extends FailedResolutionResult {
private final Collection<DexEncodedMethod> methodsCausingError;
@@ -836,6 +849,11 @@
public void forEachFailureDependency(Consumer<DexEncodedMethod> methodCausingFailureConsumer) {
this.methodsCausingError.forEach(methodCausingFailureConsumer);
}
+
+ @Override
+ public boolean hasMethodsCausingError() {
+ return methodsCausingError.size() > 0;
+ }
}
public static class IncompatibleClassResult extends FailedResolutionWithCausingMethods {
@@ -861,13 +879,70 @@
public static class NoSuchMethodResult extends FailedResolutionResult {
static final NoSuchMethodResult INSTANCE = new NoSuchMethodResult();
+
+ @Override
+ public boolean isNoSuchMethodErrorResult(DexClass context, AppInfoWithClassHierarchy appInfo) {
+ return true;
+ }
}
- public static class IllegalAccessOrNoSuchMethodResult extends FailedResolutionWithCausingMethods {
+ static class IllegalAccessOrNoSuchMethodResult extends FailedResolutionWithCausingMethods {
- public IllegalAccessOrNoSuchMethodResult(DexEncodedMethod methodCausingError) {
- super(Collections.singletonList(methodCausingError));
+ private final DexClass initialResolutionHolder;
+
+ public IllegalAccessOrNoSuchMethodResult(
+ DexClass initialResolutionHolder, Collection<DexEncodedMethod> methodsCausingError) {
+ super(methodsCausingError);
+ this.initialResolutionHolder = initialResolutionHolder;
+ }
+
+ public IllegalAccessOrNoSuchMethodResult(
+ DexClass initialResolutionHolder, DexEncodedMethod methodCausingError) {
+ this(initialResolutionHolder, Collections.singletonList(methodCausingError));
assert methodCausingError != null;
}
+
+ @Override
+ public boolean isIllegalAccessErrorResult(DexClass context, AppInfoWithClassHierarchy appInfo) {
+ if (!hasMethodsCausingError()) {
+ return false;
+ }
+ BooleanBox seenNoAccess = new BooleanBox(false);
+ forEachFailureDependency(
+ method -> {
+ DexClassAndMethod classAndMethod =
+ DexClassAndMethod.create(appInfo.definitionFor(method.getHolderType()), method);
+ seenNoAccess.or(
+ AccessControl.isMemberAccessible(
+ classAndMethod, initialResolutionHolder, context, appInfo)
+ .isFalse());
+ });
+ return seenNoAccess.get();
+ }
+
+ @Override
+ public boolean isNoSuchMethodErrorResult(DexClass context, AppInfoWithClassHierarchy appInfo) {
+ if (!hasMethodsCausingError()) {
+ return true;
+ }
+ if (isIllegalAccessErrorResult(context, appInfo)) {
+ return false;
+ }
+ // At this point we know we have methods causing errors but we have access to them. To be
+ // certain that this is the case where we have nest access but we are invoking a method with
+ // an incorrect symbolic reference, we directly test for it by having an assert.
+ assert verifyInvalidSymbolicReference();
+ return true;
+ }
+
+ private boolean verifyInvalidSymbolicReference() {
+ BooleanBox invalidSymbolicReference = new BooleanBox(true);
+ forEachFailureDependency(
+ method -> {
+ invalidSymbolicReference.and(
+ method.getHolderType() != initialResolutionHolder.getType());
+ });
+ return invalidSymbolicReference.get();
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
index add54d6..c016016 100644
--- a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
+++ b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
@@ -133,8 +133,8 @@
private final DexType oldType;
private final DexType newType;
- static RewrittenTypeInfo toVoid(DexType oldReturnType, AppView<?> appView) {
- return new RewrittenTypeInfo(oldReturnType, appView.dexItemFactory().voidType);
+ static RewrittenTypeInfo toVoid(DexType oldReturnType, DexItemFactory dexItemFactory) {
+ return new RewrittenTypeInfo(oldReturnType, dexItemFactory.voidType);
}
public RewrittenTypeInfo(DexType oldType, DexType newType) {
@@ -150,8 +150,8 @@
return oldType;
}
- boolean hasBeenChangedToReturnVoid(AppView<?> appView) {
- return newType == appView.dexItemFactory().voidType;
+ boolean hasBeenChangedToReturnVoid(DexItemFactory dexItemFactory) {
+ return newType == dexItemFactory.voidType;
}
@Override
@@ -252,7 +252,7 @@
// Currently not allowed to remove the receiver of an instance method. This would involve
// changing invoke-direct/invoke-virtual into invoke-static.
assert encodedMethod.isStatic() || !getArgumentInfo(0).isRemovedArgumentInfo();
- DexType[] params = encodedMethod.method.proto.parameters.values;
+ DexType[] params = encodedMethod.getReference().proto.parameters.values;
if (isEmpty()) {
return params;
}
@@ -367,7 +367,9 @@
ArgumentInfoCollection removedArgumentsInfo) {
DexType returnType = method.proto.returnType;
RewrittenTypeInfo returnInfo =
- returnType.isAlwaysNull(appView) ? RewrittenTypeInfo.toVoid(returnType, appView) : null;
+ returnType.isAlwaysNull(appView)
+ ? RewrittenTypeInfo.toVoid(returnType, appView.dexItemFactory())
+ : null;
return create(Collections.emptyList(), returnInfo, removedArgumentsInfo);
}
@@ -394,8 +396,9 @@
return extraParameters.size();
}
- public boolean hasBeenChangedToReturnVoid(AppView<?> appView) {
- return rewrittenReturnInfo != null && rewrittenReturnInfo.hasBeenChangedToReturnVoid(appView);
+ public boolean hasBeenChangedToReturnVoid(DexItemFactory dexItemFactory) {
+ return rewrittenReturnInfo != null
+ && rewrittenReturnInfo.hasBeenChangedToReturnVoid(dexItemFactory);
}
public ArgumentInfoCollection getArgumentInfoCollection() {
@@ -433,23 +436,23 @@
public DexProto rewriteProto(DexEncodedMethod encodedMethod, DexItemFactory dexItemFactory) {
if (isEmpty()) {
- return encodedMethod.method.proto;
+ return encodedMethod.getReference().proto;
}
DexType newReturnType =
rewrittenReturnInfo != null
? rewrittenReturnInfo.newType
- : encodedMethod.method.proto.returnType;
+ : encodedMethod.getReference().proto.returnType;
DexType[] newParameters = argumentInfoCollection.rewriteParameters(encodedMethod);
return dexItemFactory.createProto(newReturnType, newParameters);
}
public RewrittenPrototypeDescription withConstantReturn(
- DexType oldReturnType, AppView<?> appView) {
+ DexType oldReturnType, DexItemFactory dexItemFactory) {
assert rewrittenReturnInfo == null;
- return !hasBeenChangedToReturnVoid(appView)
+ return !hasBeenChangedToReturnVoid(dexItemFactory)
? new RewrittenPrototypeDescription(
extraParameters,
- RewrittenTypeInfo.toVoid(oldReturnType, appView),
+ RewrittenTypeInfo.toVoid(oldReturnType, dexItemFactory),
argumentInfoCollection)
: this;
}
diff --git a/src/main/java/com/android/tools/r8/graph/TreeFixerBase.java b/src/main/java/com/android/tools/r8/graph/TreeFixerBase.java
index 27f3251..5bbc1ee 100644
--- a/src/main/java/com/android/tools/r8/graph/TreeFixerBase.java
+++ b/src/main/java/com/android/tools/r8/graph/TreeFixerBase.java
@@ -43,7 +43,7 @@
}
private DexEncodedField recordFieldChange(DexEncodedField from, DexEncodedField to) {
- recordFieldChange(from.field, to.field);
+ recordFieldChange(from.getReference(), to.getReference());
return to;
}
@@ -77,7 +77,7 @@
/** Callback to allow custom handling when an encoded method changes. */
public DexEncodedMethod recordMethodChange(DexEncodedMethod from, DexEncodedMethod to) {
- recordMethodChange(from.method, to.method);
+ recordMethodChange(from.getReference(), to.getReference());
return to;
}
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 0e7d164..a47acd6 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -63,7 +63,6 @@
private final DexItemFactory dexItemFactory;
private final ClassInitializerSynthesizedCode classInitializerSynthesizedCode;
private final HorizontalClassMergerGraphLens.Builder lensBuilder;
- private final HorizontallyMergedClasses.Builder mergedClassesBuilder;
private final ClassMethodsBuilder classMethodsBuilder = new ClassMethodsBuilder();
private final Reference2IntMap<DexType> classIdentifiers = new Reference2IntOpenHashMap<>();
@@ -75,14 +74,12 @@
private ClassMerger(
AppView<AppInfoWithLiveness> appView,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- HorizontallyMergedClasses.Builder mergedClassesBuilder,
MergeGroup group,
Collection<VirtualMethodMerger> virtualMethodMergers,
Collection<ConstructorMerger> constructorMergers,
ClassInitializerSynthesizedCode classInitializerSynthesizedCode) {
this.appView = appView;
this.lensBuilder = lensBuilder;
- this.mergedClassesBuilder = mergedClassesBuilder;
this.group = group;
this.virtualMethodMergers = virtualMethodMergers;
this.constructorMergers = constructorMergers;
@@ -95,10 +92,6 @@
buildClassIdentifierMap();
}
- MergeGroup getGroup() {
- return group;
- }
-
void buildClassIdentifierMap() {
classIdentifiers.put(group.getTarget().getType(), 0);
group.forEachSource(clazz -> classIdentifiers.put(clazz.getType(), classIdentifiers.size()));
@@ -174,7 +167,7 @@
DexMethod renameDirectMethod(ProgramMethod method) {
assert method.getDefinition().belongsToDirectPool();
return dexItemFactory.createFreshMethodName(
- method.getDefinition().method.name.toSourceString(),
+ method.getDefinition().getReference().name.toSourceString(),
method.getHolderType(),
method.getDefinition().getProto(),
group.getTarget().getType(),
@@ -279,8 +272,6 @@
mergeStaticFields();
mergeInstanceFields();
-
- mergedClassesBuilder.addMergeGroup(group);
}
public static class Builder {
@@ -351,7 +342,6 @@
}
public ClassMerger build(
- HorizontallyMergedClasses.Builder mergedClassesBuilder,
HorizontalClassMergerGraphLens.Builder lensBuilder) {
setup();
List<VirtualMethodMerger> virtualMethodMergers =
@@ -377,7 +367,6 @@
return new ClassMerger(
appView,
lensBuilder,
- mergedClassesBuilder,
group,
virtualMethodMergers,
constructorMergers,
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 05e91a4..7085879 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -40,8 +40,8 @@
import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.shaking.RuntimeTypeCheckInfo;
+import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -56,14 +56,13 @@
assert appView.options().enableInlining;
}
- public HorizontalClassMergerResult run(
- RuntimeTypeCheckInfo runtimeTypeCheckInfo) {
+ public HorizontalClassMergerResult run(RuntimeTypeCheckInfo runtimeTypeCheckInfo, Timing timing) {
MergeGroup initialGroup = new MergeGroup(appView.appInfo().classesWithDeterministicOrder());
// Run the policies on all program classes to produce a final grouping.
List<Policy> policies = getPolicies(runtimeTypeCheckInfo);
Collection<MergeGroup> groups =
- new SimplePolicyExecutor().run(Collections.singletonList(initialGroup), policies);
+ new PolicyExecutor().run(Collections.singletonList(initialGroup), policies, timing);
// If there are no groups, then end horizontal class merging.
if (groups.isEmpty()) {
@@ -71,25 +70,18 @@
return null;
}
- HorizontallyMergedClasses.Builder mergedClassesBuilder =
- new HorizontallyMergedClasses.Builder();
HorizontalClassMergerGraphLens.Builder lensBuilder =
new HorizontalClassMergerGraphLens.Builder();
- // Set up a class merger for each group.
- List<ClassMerger> classMergers =
- initializeClassMergers(mergedClassesBuilder, lensBuilder, groups);
- Iterable<DexProgramClass> allMergeClasses =
- Iterables.concat(
- Iterables.transform(classMergers, classMerger -> classMerger.getGroup().getClasses()));
-
// Merge the classes.
+ List<ClassMerger> classMergers = initializeClassMergers(lensBuilder, groups);
SyntheticArgumentClass syntheticArgumentClass =
- new SyntheticArgumentClass.Builder(appView).build(allMergeClasses);
+ new SyntheticArgumentClass.Builder(appView).build(groups);
applyClassMergers(classMergers, syntheticArgumentClass);
// Generate the graph lens.
- HorizontallyMergedClasses mergedClasses = mergedClassesBuilder.build();
+ HorizontallyMergedClasses mergedClasses =
+ HorizontallyMergedClasses.builder().addMergeGroups(groups).build();
appView.setHorizontallyMergedClasses(mergedClasses);
HorizontalClassMergerGraphLens lens =
createLens(mergedClasses, lensBuilder, syntheticArgumentClass);
@@ -163,7 +155,6 @@
* be merged and how the merging should be performed.
*/
private List<ClassMerger> initializeClassMergers(
- HorizontallyMergedClasses.Builder mergedClassesBuilder,
HorizontalClassMergerGraphLens.Builder lensBuilder,
Collection<MergeGroup> groups) {
List<ClassMerger> classMergers = new ArrayList<>();
@@ -171,8 +162,7 @@
// TODO(b/166577694): Replace Collection<DexProgramClass> with MergeGroup
for (MergeGroup group : groups) {
assert !group.isEmpty();
- ClassMerger merger =
- new ClassMerger.Builder(appView, group).build(mergedClassesBuilder, lensBuilder);
+ ClassMerger merger = new ClassMerger.Builder(appView, group).build(lensBuilder);
classMergers.add(merger);
}
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 f5fdd6f..4358dc8 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -8,14 +8,12 @@
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.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.ir.conversion.ExtraParameter;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
-import com.android.tools.r8.utils.collections.BidirectionalOneToManyRepresentativeHashMap;
-import com.android.tools.r8.utils.collections.BidirectionalOneToManyRepresentativeMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
@@ -36,14 +34,8 @@
Map<DexMethod, List<ExtraParameter>> methodExtraParameters,
BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
Map<DexMethod, DexMethod> methodMap,
- BidirectionalOneToManyRepresentativeMap<DexMethod, DexMethod> originalMethodSignatures) {
- super(
- mergedClasses.getForwardMap(),
- methodMap,
- fieldMap,
- originalMethodSignatures,
- appView.graphLens(),
- appView.dexItemFactory());
+ BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> newMethodSignatures) {
+ super(appView, fieldMap, methodMap, mergedClasses.getForwardMap(), newMethodSignatures);
this.methodExtraParameters = methodExtraParameters;
this.mergedClasses = mergedClasses;
}
@@ -91,32 +83,33 @@
public static class Builder {
private final MutableBidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap =
- new BidirectionalManyToOneRepresentativeHashMap<>();
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
private final BidirectionalManyToOneHashMap<DexMethod, DexMethod> methodMap =
- new BidirectionalManyToOneHashMap<>();
- private final BidirectionalOneToManyRepresentativeHashMap<DexMethod, DexMethod>
- originalMethodSignatures = new BidirectionalOneToManyRepresentativeHashMap<>();
+ BidirectionalManyToOneHashMap.newIdentityHashMap();
+ private final BidirectionalManyToOneRepresentativeHashMap<DexMethod, DexMethod>
+ newMethodSignatures = BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
private final Map<DexMethod, List<ExtraParameter>> methodExtraParameters =
new IdentityHashMap<>();
private final BidirectionalManyToOneHashMap<DexMethod, DexMethod> pendingMethodMapUpdates =
- new BidirectionalManyToOneHashMap<>();
- private final BidirectionalOneToManyRepresentativeHashMap<DexMethod, DexMethod>
- pendingOriginalMethodSignatureUpdates = new BidirectionalOneToManyRepresentativeHashMap<>();
+ BidirectionalManyToOneHashMap.newIdentityHashMap();
+ private final BidirectionalManyToOneRepresentativeHashMap<DexMethod, DexMethod>
+ pendingNewMethodSignatureUpdates =
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
Builder() {}
HorizontalClassMergerGraphLens build(
AppView<?> appView, HorizontallyMergedClasses mergedClasses) {
assert pendingMethodMapUpdates.isEmpty();
- assert pendingOriginalMethodSignatureUpdates.isEmpty();
+ assert pendingNewMethodSignatureUpdates.isEmpty();
return new HorizontalClassMergerGraphLens(
appView,
mergedClasses,
methodExtraParameters,
fieldMap,
methodMap.getForwardMap(),
- originalMethodSignatures);
+ newMethodSignatures);
}
void recordNewFieldSignature(DexField oldFieldSignature, DexField newFieldSignature) {
@@ -161,7 +154,7 @@
}
void recordNewMethodSignature(DexMethod oldMethodSignature, DexMethod newMethodSignature) {
- originalMethodSignatures.put(newMethodSignature, oldMethodSignature);
+ newMethodSignatures.put(oldMethodSignature, newMethodSignature);
}
void fixupMethod(DexMethod oldMethodSignature, DexMethod newMethodSignature) {
@@ -182,12 +175,12 @@
private void fixupOriginalMethodSignatures(
DexMethod oldMethodSignature, DexMethod newMethodSignature) {
- Set<DexMethod> oldMethodSignatures = originalMethodSignatures.getValues(oldMethodSignature);
+ Set<DexMethod> oldMethodSignatures = newMethodSignatures.getKeys(oldMethodSignature);
if (oldMethodSignatures.isEmpty()) {
- pendingOriginalMethodSignatureUpdates.put(newMethodSignature, oldMethodSignature);
+ pendingNewMethodSignatureUpdates.put(oldMethodSignature, newMethodSignature);
} else {
for (DexMethod originalMethodSignature : oldMethodSignatures) {
- pendingOriginalMethodSignatureUpdates.put(newMethodSignature, originalMethodSignature);
+ pendingNewMethodSignatureUpdates.put(originalMethodSignature, newMethodSignature);
}
}
}
@@ -199,9 +192,9 @@
pendingMethodMapUpdates.clear();
// Commit pending original method signatures updates.
- originalMethodSignatures.removeAll(pendingOriginalMethodSignatureUpdates.keySet());
- pendingOriginalMethodSignatureUpdates.forEachOneToManyMapping(originalMethodSignatures::put);
- pendingOriginalMethodSignatureUpdates.clear();
+ newMethodSignatures.removeAll(pendingNewMethodSignatureUpdates.keySet());
+ pendingNewMethodSignatureUpdates.forEachManyToOneMapping(newMethodSignatures::put);
+ pendingNewMethodSignatureUpdates.clear();
}
/**
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
index 93f9d3f..927e629 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
@@ -24,6 +24,10 @@
this.mergedClasses = mergedClasses;
}
+ static Builder builder() {
+ return new Builder();
+ }
+
public static HorizontallyMergedClasses empty() {
return new HorizontallyMergedClasses(new EmptyBidirectionalOneToOneMap<>());
}
@@ -79,15 +83,21 @@
}
public static class Builder {
- private final MutableBidirectionalManyToOneMap<DexType, DexType> mergedClasses =
- new BidirectionalManyToOneHashMap<>();
- public HorizontallyMergedClasses build() {
- return new HorizontallyMergedClasses(mergedClasses);
+ private final MutableBidirectionalManyToOneMap<DexType, DexType> mergedClasses =
+ BidirectionalManyToOneHashMap.newIdentityHashMap();
+
+ void addMergeGroup(MergeGroup group) {
+ group.forEachSource(clazz -> mergedClasses.put(clazz.getType(), group.getTarget().getType()));
}
- public void addMergeGroup(MergeGroup group) {
- group.forEachSource(clazz -> mergedClasses.put(clazz.getType(), group.getTarget().getType()));
+ Builder addMergeGroups(Iterable<MergeGroup> groups) {
+ groups.forEach(this::addMergeGroup);
+ return this;
+ }
+
+ HorizontallyMergedClasses build() {
+ return new HorizontallyMergedClasses(mergedClasses);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/Policy.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/Policy.java
index 4642229..b984ed5 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/Policy.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/Policy.java
@@ -14,6 +14,8 @@
public void clear() {}
+ public abstract String getName();
+
public boolean shouldSkipPolicy() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java
index b94adf8..33b6f7f 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java
@@ -4,15 +4,88 @@
package com.android.tools.r8.horizontalclassmerging;
+import com.android.tools.r8.utils.IterableUtils;
+import com.android.tools.r8.utils.Timing;
import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
-public abstract class PolicyExecutor {
+/**
+ * This is a simple policy executor that ensures regular sequential execution of policies. It should
+ * primarily be readable and correct. The SimplePolicyExecutor should be a reference implementation,
+ * against which more efficient policy executors can be compared.
+ */
+public class PolicyExecutor {
+
+ // TODO(b/165506334): if performing mutable operation ensure that linked lists are used
+ private void applySingleClassPolicy(SingleClassPolicy policy, LinkedList<MergeGroup> groups) {
+ Iterator<MergeGroup> i = groups.iterator();
+ while (i.hasNext()) {
+ MergeGroup group = i.next();
+ int previousNumberOfClasses = group.size();
+ group.removeIf(clazz -> !policy.canMerge(clazz));
+ policy.numberOfRemovedClasses += previousNumberOfClasses - group.size();
+ if (group.size() < 2) {
+ i.remove();
+ }
+ }
+ }
+
+ private LinkedList<MergeGroup> applyMultiClassPolicy(
+ MultiClassPolicy policy, LinkedList<MergeGroup> groups) {
+ // For each group apply the multi class policy and add all the new groups together.
+ LinkedList<MergeGroup> newGroups = new LinkedList<>();
+ groups.forEach(
+ group -> {
+ int previousNumberOfClasses = group.size();
+ Collection<MergeGroup> policyGroups = policy.apply(group);
+ policyGroups.forEach(newGroup -> newGroup.applyMetadataFrom(group));
+ policy.numberOfRemovedClasses +=
+ previousNumberOfClasses - IterableUtils.sumInt(policyGroups, MergeGroup::size);
+ newGroups.addAll(policyGroups);
+ });
+ return newGroups;
+ }
/**
* Given an initial collection of class groups which can potentially be merged, run all of the
* policies registered to this policy executor on the class groups yielding a new collection of
* class groups.
*/
- public abstract Collection<MergeGroup> run(
- Collection<MergeGroup> classes, Collection<Policy> policies);
+ public Collection<MergeGroup> run(
+ Collection<MergeGroup> inputGroups, Collection<Policy> policies, Timing timing) {
+ LinkedList<MergeGroup> linkedGroups;
+
+ if (inputGroups instanceof LinkedList) {
+ linkedGroups = (LinkedList<MergeGroup>) inputGroups;
+ } else {
+ linkedGroups = new LinkedList<>(inputGroups);
+ }
+
+ for (Policy policy : policies) {
+ if (policy.shouldSkipPolicy()) {
+ continue;
+ }
+
+ timing.begin(policy.getName());
+ if (policy instanceof SingleClassPolicy) {
+ applySingleClassPolicy((SingleClassPolicy) policy, linkedGroups);
+ } else {
+ assert policy instanceof MultiClassPolicy;
+ linkedGroups = applyMultiClassPolicy((MultiClassPolicy) policy, linkedGroups);
+ }
+ timing.end();
+
+ policy.clear();
+
+ if (linkedGroups.isEmpty()) {
+ break;
+ }
+
+ // Any policy should not return any trivial groups.
+ assert linkedGroups.stream().allMatch(group -> group.size() >= 2);
+ }
+
+ return linkedGroups;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/SimplePolicyExecutor.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/SimplePolicyExecutor.java
deleted file mode 100644
index 3b96a76..0000000
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/SimplePolicyExecutor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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.
-
-package com.android.tools.r8.horizontalclassmerging;
-
-import com.android.tools.r8.utils.IterableUtils;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-
-/**
- * This is a simple policy executor that ensures regular sequential execution of policies. It should
- * primarily be readable and correct. The SimplePolicyExecutor should be a reference implementation,
- * against which more efficient policy executors can be compared.
- */
-public class SimplePolicyExecutor extends PolicyExecutor {
-
- // TODO(b/165506334): if performing mutable operation ensure that linked lists are used
- private LinkedList<MergeGroup> applySingleClassPolicy(
- SingleClassPolicy policy, LinkedList<MergeGroup> groups) {
- Iterator<MergeGroup> i = groups.iterator();
- while (i.hasNext()) {
- MergeGroup group = i.next();
- int previousNumberOfClasses = group.size();
- group.removeIf(clazz -> !policy.canMerge(clazz));
- policy.numberOfRemovedClasses += previousNumberOfClasses - group.size();
- if (group.size() < 2) {
- i.remove();
- }
- }
- return groups;
- }
-
- private LinkedList<MergeGroup> applyMultiClassPolicy(
- MultiClassPolicy policy, LinkedList<MergeGroup> groups) {
- // For each group apply the multi class policy and add all the new groups together.
- LinkedList<MergeGroup> newGroups = new LinkedList<>();
- groups.forEach(
- group -> {
- int previousNumberOfClasses = group.size();
- Collection<MergeGroup> policyGroups = policy.apply(group);
- policyGroups.forEach(newGroup -> newGroup.applyMetadataFrom(group));
- policy.numberOfRemovedClasses +=
- previousNumberOfClasses - IterableUtils.sumInt(policyGroups, MergeGroup::size);
- newGroups.addAll(policyGroups);
- });
- return newGroups;
- }
-
- @Override
- public Collection<MergeGroup> run(
- Collection<MergeGroup> inputGroups, Collection<Policy> policies) {
- LinkedList<MergeGroup> linkedGroups;
-
- if (inputGroups instanceof LinkedList) {
- linkedGroups = (LinkedList<MergeGroup>) inputGroups;
- } else {
- linkedGroups = new LinkedList<>(inputGroups);
- }
-
- for (Policy policy : policies) {
- if (policy.shouldSkipPolicy()) {
- continue;
- }
-
- if (policy instanceof SingleClassPolicy) {
- linkedGroups = applySingleClassPolicy((SingleClassPolicy) policy, linkedGroups);
- } else if (policy instanceof MultiClassPolicy) {
- linkedGroups = applyMultiClassPolicy((MultiClassPolicy) policy, linkedGroups);
- }
-
- policy.clear();
-
- if (linkedGroups.isEmpty()) {
- break;
- }
-
- // Any policy should not return any trivial groups.
- assert linkedGroups.stream().allMatch(group -> group.size() >= 2);
- }
-
- return linkedGroups;
- }
-}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
index ca0b752..c8cc19e 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
/**
@@ -55,9 +56,8 @@
.createFixedClass(syntheticKind, context, appView.dexItemFactory(), builder -> {});
}
- public SyntheticArgumentClass build(Iterable<DexProgramClass> mergeClasses) {
- // Find a fresh name in an existing package.
- DexProgramClass context = mergeClasses.iterator().next();
+ public SyntheticArgumentClass build(Collection<MergeGroup> mergeGroups) {
+ DexProgramClass context = getDeterministicContext(mergeGroups);
List<DexType> syntheticArgumentTypes = new ArrayList<>();
syntheticArgumentTypes.add(
synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_1).getType());
@@ -67,5 +67,12 @@
synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_3).getType());
return new SyntheticArgumentClass(syntheticArgumentTypes);
}
+
+ private static DexProgramClass getDeterministicContext(Collection<MergeGroup> mergeGroups) {
+ // Relies on the determinism of the merge groups.
+ MergeGroup mergeGroup = mergeGroups.iterator().next();
+ assert mergeGroup.hasTarget();
+ return mergeGroup.getTarget();
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index e8130ed..c144128 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -112,7 +112,7 @@
flags.setPrivate();
classMethodsBuilder.addDirectMethod(encodedMethod);
- return encodedMethod.method;
+ return encodedMethod.getReference();
}
private MethodAccessFlags getAccessFlags() {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AllInstantiatedOrUninstantiated.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AllInstantiatedOrUninstantiated.java
index 75d61d9..38150db 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AllInstantiatedOrUninstantiated.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AllInstantiatedOrUninstantiated.java
@@ -21,4 +21,9 @@
public Boolean getMergeKey(DexProgramClass clazz) {
return appView.appInfo().isInstantiatedDirectlyOrIndirectly(clazz);
}
+
+ @Override
+ public String getName() {
+ return "AllInstantiatedOrUninstantiated";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/CheckAbstractClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/CheckAbstractClasses.java
index 6e5c711..e78b196 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/CheckAbstractClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/CheckAbstractClasses.java
@@ -25,6 +25,11 @@
}
@Override
+ public String getName() {
+ return "CheckAbstractClasses";
+ }
+
+ @Override
public boolean shouldSkipPolicy() {
// We can just make the target class non-abstract if one of the classes in the group
// is non-abstract.
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java
index f7d121a..e6e67e0 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java
@@ -12,16 +12,14 @@
import com.android.tools.r8.horizontalclassmerging.SingleClassPolicy;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.MainDexInfo;
import com.google.common.collect.Iterables;
public class DontInlinePolicy extends SingleClassPolicy {
+
private final AppView<AppInfoWithLiveness> appView;
- private final MainDexInfo mainDexInfo;
public DontInlinePolicy(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
- this.mainDexInfo = appView.appInfo().getMainDexInfo();
}
private boolean disallowInlining(ProgramMethod method) {
@@ -53,4 +51,9 @@
program.directProgramMethods(),
method -> method.getDefinition().isInstanceInitializer() && disallowInlining(method));
}
+
+ @Override
+ public String getName() {
+ return "DontInlinePolicy";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontMergeSynchronizedClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontMergeSynchronizedClasses.java
index 4372869..e1cb9a7 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontMergeSynchronizedClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontMergeSynchronizedClasses.java
@@ -56,4 +56,9 @@
return synchronizedGroups;
}
+
+ @Override
+ public String getName() {
+ return "DontMergeSynchronizedClasses";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitGroups.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitGroups.java
index 33de8f3..80e1292 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitGroups.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitGroups.java
@@ -52,4 +52,9 @@
newGroups.add(newGroup);
return newGroup;
}
+
+ @Override
+ public String getName() {
+ return "LimitGroups";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/MinimizeFieldCasts.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/MinimizeFieldCasts.java
index 73e0786..1ef2f6a 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/MinimizeFieldCasts.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/MinimizeFieldCasts.java
@@ -70,4 +70,9 @@
}
return fieldTypes;
}
+
+ @Override
+ public String getName() {
+ return "MinimizeFieldCasts";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoAnnotationClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoAnnotationClasses.java
index 1effb8b..9943010 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoAnnotationClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoAnnotationClasses.java
@@ -12,4 +12,9 @@
public boolean canMerge(DexProgramClass program) {
return !program.isAnnotation();
}
+
+ @Override
+ public String getName() {
+ return "NoAnnotationClasses";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassAnnotationCollisions.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassAnnotationCollisions.java
index 9d3d730..1a96901 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassAnnotationCollisions.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassAnnotationCollisions.java
@@ -41,4 +41,9 @@
}
return removeTrivialGroups(newGroups);
}
+
+ @Override
+ public String getName() {
+ return "NoClassAnnotationCollisions";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerWithObservableSideEffects.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerWithObservableSideEffects.java
index f10d78c..b156a2e 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerWithObservableSideEffects.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerWithObservableSideEffects.java
@@ -28,4 +28,9 @@
return program.getKotlinInfo().isSyntheticClass()
&& program.getKotlinInfo().asSyntheticClass().isLambda();
}
+
+ @Override
+ public String getName() {
+ return "NoClassInitializerWithObservableSideEffects";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDirectRuntimeTypeChecks.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDirectRuntimeTypeChecks.java
index b0f3766..17659f8 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDirectRuntimeTypeChecks.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDirectRuntimeTypeChecks.java
@@ -19,4 +19,9 @@
public boolean canMerge(DexProgramClass clazz) {
return !runtimeTypeCheckInfo.isRuntimeCheckType(clazz);
}
+
+ @Override
+ public String getName() {
+ return "NoDirectRuntimeTypeChecks";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoEnums.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoEnums.java
index c8a0aab..8bea8a4 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoEnums.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoEnums.java
@@ -27,6 +27,11 @@
}
@Override
+ public String getName() {
+ return "NoEnums";
+ }
+
+ @Override
public boolean canMerge(DexProgramClass program) {
if (program.isEnum()) {
return false;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoIndirectRuntimeTypeChecks.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoIndirectRuntimeTypeChecks.java
index 7446787..8de67d6 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoIndirectRuntimeTypeChecks.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoIndirectRuntimeTypeChecks.java
@@ -65,4 +65,9 @@
}
return false;
}
+
+ @Override
+ public String getName() {
+ return "NoIndirectRuntimeTypeChecks";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInnerClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInnerClasses.java
index cc9f61c..1d26825 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInnerClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInnerClasses.java
@@ -14,4 +14,9 @@
// TODO(b/179018501): allow merging classes with inner/outer classes.
return program.getInnerClasses().isEmpty();
}
+
+ @Override
+ public String getName() {
+ return "NoInnerClasses";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInstanceFieldAnnotations.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInstanceFieldAnnotations.java
index 610af7e..229c062 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInstanceFieldAnnotations.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInstanceFieldAnnotations.java
@@ -19,4 +19,9 @@
}
return true;
}
+
+ @Override
+ public String getName() {
+ return "NoInstanceFieldAnnotations";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInterfaces.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInterfaces.java
index 63df0de..d6032e7 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInterfaces.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoInterfaces.java
@@ -13,4 +13,9 @@
public boolean canMerge(DexProgramClass program) {
return !program.isInterface();
}
+
+ @Override
+ public String getName() {
+ return "NoInterfaces";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKeepRules.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKeepRules.java
index e0a39eb..ec8a5aa 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKeepRules.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKeepRules.java
@@ -49,4 +49,9 @@
public boolean canMerge(DexProgramClass program) {
return !dontMergeTypes.contains(program.getType());
}
+
+ @Override
+ public String getName() {
+ return "NoKeepRules";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKotlinMetadata.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKotlinMetadata.java
index 1acad7a..7783f20 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKotlinMetadata.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoKotlinMetadata.java
@@ -29,4 +29,9 @@
.allMatch(member -> member.getKotlinMemberInfo().isNoKotlinInformation());
return true;
}
+
+ @Override
+ public String getName() {
+ return "NoKotlinMetadata";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoNativeMethods.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoNativeMethods.java
index f1a278c..a32d083 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoNativeMethods.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoNativeMethods.java
@@ -14,4 +14,9 @@
public boolean canMerge(DexProgramClass program) {
return !Iterables.any(program.methods(), DexEncodedMethod::isNative);
}
+
+ @Override
+ public String getName() {
+ return "NoNativeMethods";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoServiceLoaders.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoServiceLoaders.java
index 1c6ae77..b1f0d99 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoServiceLoaders.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoServiceLoaders.java
@@ -26,4 +26,9 @@
return !appView.appServices().allServiceTypes().contains(program.getType())
&& !allServiceImplementations.contains(program.getType());
}
+
+ @Override
+ public String getName() {
+ return "NoServiceLoaders";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java
index bfe0f2a..8751afb 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java
@@ -30,4 +30,9 @@
return !deadEnumLiteMaps.contains(program.getType())
&& !appView.appInfo().isNoHorizontalClassMergingOfType(program.getType());
}
+
+ @Override
+ public String getName() {
+ return "NotMatchedByNoHorizontalClassMerging";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotVerticallyMergedIntoSubtype.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotVerticallyMergedIntoSubtype.java
index 67afbc3..92d50d1 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotVerticallyMergedIntoSubtype.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotVerticallyMergedIntoSubtype.java
@@ -23,4 +23,9 @@
}
return !appView.verticallyMergedClasses().hasBeenMergedIntoSubtype(program.type);
}
+
+ @Override
+ public String getName() {
+ return "NotVerticallyMergedIntoSubtype";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java
index 4a789ba..c8bb5c6 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java
@@ -28,6 +28,11 @@
*/
public class PreserveMethodCharacteristics extends MultiClassPolicy {
+ @Override
+ public String getName() {
+ return "PreserveMethodCharacteristics";
+ }
+
static class MethodCharacteristics {
private final MethodAccessFlags accessFlags;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java
index 41c240f..38df5cf 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java
@@ -29,4 +29,9 @@
? mainDexInfo.getMergeKey(clazz, synthetics)
: ineligibleForClassMerging();
}
+
+ @Override
+ public String getName() {
+ return "PreventMergeIntoDifferentMainDexGroups";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMethodImplementation.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMethodImplementation.java
index c7c57c8..b182330 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMethodImplementation.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMethodImplementation.java
@@ -59,6 +59,11 @@
private final ReservedInterfaceSignaturesFor reservedInterfaceSignaturesFor =
new ReservedInterfaceSignaturesFor();
+ @Override
+ public String getName() {
+ return "PreventMethodImplementation";
+ }
+
private abstract static class SignaturesCache<C extends DexClass> {
private final Map<DexClass, DexMethodSignatureSet> memoizedSignatures = new IdentityHashMap<>();
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
index 914fc57..78cfe13 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
@@ -96,4 +96,9 @@
groups.addAll(restrictedClasses.values());
return groups;
}
+
+ @Override
+ public String getName() {
+ return "RespectPackageBoundaries";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameFeatureSplit.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameFeatureSplit.java
index 20caa50..b3ec017 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameFeatureSplit.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameFeatureSplit.java
@@ -24,4 +24,9 @@
.getClassToFeatureSplitMap()
.getFeatureSplit(clazz, appView.getSyntheticItems());
}
+
+ @Override
+ public String getName() {
+ return "SameFeatureSplit";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameInstanceFields.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameInstanceFields.java
index 13e0388..291aae5 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameInstanceFields.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameInstanceFields.java
@@ -34,6 +34,11 @@
return fields;
}
+ @Override
+ public String getName() {
+ return "SameInstanceFields";
+ }
+
public static class InstanceFieldInfo {
private final FieldAccessFlags accessFlags;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameNestHost.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameNestHost.java
index 88d2984..fc8e39c 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameNestHost.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameNestHost.java
@@ -23,4 +23,9 @@
public DexType getMergeKey(DexProgramClass clazz) {
return clazz.isInANest() ? clazz.getNestHost() : dexItemFactory.objectType;
}
+
+ @Override
+ public String getName() {
+ return "SameNestHost";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameParentClass.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameParentClass.java
index 12c8e31..3afa656 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameParentClass.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SameParentClass.java
@@ -14,4 +14,9 @@
public DexType getMergeKey(DexProgramClass clazz) {
return clazz.superType;
}
+
+ @Override
+ public String getName() {
+ return "SameParentClass";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SyntheticItemsPolicy.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SyntheticItemsPolicy.java
index b012897..cbc9b3d 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SyntheticItemsPolicy.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SyntheticItemsPolicy.java
@@ -48,4 +48,9 @@
// Java lambda merging is disabled.
return ineligibleForClassMerging();
}
+
+ @Override
+ public String getName() {
+ return "SyntheticItemsPolicy";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/inspector/internal/FieldInspectorImpl.java b/src/main/java/com/android/tools/r8/inspector/internal/FieldInspectorImpl.java
index 056d652e..c7e0cbb 100644
--- a/src/main/java/com/android/tools/r8/inspector/internal/FieldInspectorImpl.java
+++ b/src/main/java/com/android/tools/r8/inspector/internal/FieldInspectorImpl.java
@@ -26,8 +26,8 @@
reference =
Reference.field(
parent.getClassReference(),
- field.field.name.toString(),
- Reference.typeFromDescriptor(field.field.type.toDescriptorString()));
+ field.getReference().name.toString(),
+ Reference.typeFromDescriptor(field.getReference().type.toDescriptorString()));
}
return reference;
}
@@ -45,7 +45,7 @@
@Override
public Optional<ValueInspector> getInitialValue() {
if (field.isStatic() && field.getStaticValue() != null) {
- return Optional.of(new ValueInspectorImpl(field.getStaticValue(), field.field.type));
+ return Optional.of(new ValueInspectorImpl(field.getStaticValue(), field.getReference().type));
}
return Optional.empty();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/internal/MethodInspectorImpl.java b/src/main/java/com/android/tools/r8/inspector/internal/MethodInspectorImpl.java
index 1d868be..3c27924 100644
--- a/src/main/java/com/android/tools/r8/inspector/internal/MethodInspectorImpl.java
+++ b/src/main/java/com/android/tools/r8/inspector/internal/MethodInspectorImpl.java
@@ -27,14 +27,14 @@
reference =
Reference.method(
parent.getClassReference(),
- method.method.name.toString(),
+ method.getReference().name.toString(),
ListUtils.map(
- Arrays.asList(method.method.proto.parameters.values),
+ Arrays.asList(method.getReference().proto.parameters.values),
param -> Reference.typeFromDescriptor(param.toDescriptorString())),
- method.method.proto.returnType.isVoidType()
+ method.getReference().proto.returnType.isVoidType()
? null
: Reference.typeFromDescriptor(
- method.method.proto.returnType.toDescriptorString()));
+ method.getReference().proto.returnType.toDescriptorString()));
}
return reference;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java b/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
index 5926ecc..b2b6111 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
@@ -72,7 +72,8 @@
}
TypeElement valueType = instruction.returnValue().getType();
TypeElement returnType =
- TypeElement.fromDexType(method.method.proto.returnType, Nullability.maybeNull(), appView);
+ TypeElement.fromDexType(
+ method.getReference().proto.returnType, Nullability.maybeNull(), appView);
if (verifyTypesHelper.isAssignable(valueType, returnType)) {
return true;
}
@@ -80,7 +81,7 @@
if (returnType.isClassType() && valueType.isReferenceType()) {
// Interface types are treated like Object according to the JVM spec.
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.1.2-100
- DexClass clazz = appView.definitionFor(method.method.proto.returnType);
+ DexClass clazz = appView.definitionFor(method.getReference().proto.returnType);
return clazz != null && clazz.isInterface();
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index 2b63089..d1b411a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -102,7 +102,7 @@
Map<DexEncodedField, AbstractValue> abstractInstanceFieldValuesForClass =
new IdentityHashMap<>();
for (DexEncodedField field : clazz.instanceFields()) {
- FieldAccessInfo fieldAccessInfo = fieldAccessInfos.get(field.field);
+ FieldAccessInfo fieldAccessInfo = fieldAccessInfos.get(field.getReference());
if (fieldAccessInfo != null && !fieldAccessInfo.hasReflectiveAccess()) {
abstractInstanceFieldValuesForClass.put(field, BottomValue.getInstance());
}
@@ -112,14 +112,14 @@
}
private boolean isAlwaysZero(DexEncodedField field) {
- return !appView.appInfo().isPinned(field.field) && !nonZeroFields.contains(field);
+ return !appView.appInfo().isPinned(field.getReference()) && !nonZeroFields.contains(field);
}
void acceptClassInitializerDefaultsResult(
ClassInitializerDefaultsResult classInitializerDefaultsResult) {
classInitializerDefaultsResult.forEachOptimizedField(
(field, value) -> {
- if (!value.isDefault(field.field.type)) {
+ if (!value.isDefault(field.getReference().type)) {
nonZeroFields.add(field);
}
});
@@ -223,11 +223,6 @@
>= initialAbstractValue.getAbstractionSize()) {
abstractValue = UnknownValue.getInstance();
}
- } else {
- assert false
- : "Expected abstract value of "
- + field.toSourceString()
- + " to be instance of NonConstantNumberValue";
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessAnalysis.java
index a178a69..a1e3eb5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessAnalysis.java
@@ -17,7 +17,7 @@
public void recordFieldAccess(
FieldInstruction instruction, DexEncodedField field, OptimizationFeedback feedback) {
- if (!field.field.type.isIntType()) {
+ if (!field.getReference().type.isIntType()) {
return;
}
@@ -79,7 +79,7 @@
}
if (user.isFieldPut()) {
FieldInstruction fieldInstruction = user.asFieldInstruction();
- if (fieldInstruction.getField() == encodedField.field) {
+ if (fieldInstruction.getField() == encodedField.getReference()) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
index 05259ca..b11431e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
@@ -134,7 +134,7 @@
private void clearReadsAndWritesFromFieldsOfInterest(AppInfoWithLiveness appInfo) {
FieldAccessInfoCollection<?> fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
for (DexEncodedField field : constantFields) {
- fieldAccessInfoCollection.get(field.field).asMutable().clearReads();
+ fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
}
for (DexEncodedField field : readFields.keySet()) {
fieldAccessInfoCollection.get(field.getReference()).asMutable().clearWrites();
@@ -165,7 +165,7 @@
private static FieldClassification classifyField(
DexEncodedField field, AppView<AppInfoWithLiveness> appView) {
FieldAccessInfo fieldAccessInfo =
- appView.appInfo().getFieldAccessInfoCollection().get(field.field);
+ appView.appInfo().getFieldAccessInfoCollection().get(field.getReference());
if (fieldAccessInfo == null
|| fieldAccessInfo.hasReflectiveAccess()
|| fieldAccessInfo.isAccessedFromMethodHandle()
@@ -184,7 +184,7 @@
if (singleValue.isSingleFieldValue()) {
SingleFieldValue singleFieldValue = singleValue.asSingleFieldValue();
DexField singleField = singleFieldValue.getField();
- if (singleField != field.field
+ if (singleField != field.getReference()
&& !singleFieldValue.mayHaveFinalizeMethodDirectlyOrIndirectly(appView)) {
return FieldClassification.CONSTANT;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java
index 5bf0c61..f84e13d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java
@@ -73,7 +73,7 @@
assert !isEmpty();
ConcreteMutableFieldSet rewrittenSet = new ConcreteMutableFieldSet();
for (DexEncodedField field : fields) {
- DexField rewrittenFieldReference = lens.lookupField(field.field);
+ DexField rewrittenFieldReference = lens.lookupField(field.getReference());
DexClass holder = appView.definitionForHolder(rewrittenFieldReference);
DexEncodedField rewrittenField = rewrittenFieldReference.lookupOnClass(holder);
if (rewrittenField == null) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index fc01602..13d03d5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -150,7 +150,7 @@
// Dynamic upper bound type.
TypeElement fieldType =
- TypeElement.fromDexType(field.field.type, Nullability.maybeNull(), appView);
+ TypeElement.fromDexType(field.getReference().type, Nullability.maybeNull(), appView);
TypeElement dynamicUpperBoundType = value.getDynamicUpperBoundType(appView);
if (dynamicUpperBoundType.strictlyLessThan(fieldType, appView)) {
if (maybeNull && dynamicUpperBoundType.isDefinitelyNotNull()) {
@@ -201,7 +201,7 @@
}
return appView
.abstractValueFactory()
- .createSingleFieldValue(field.field, computeObjectState(value));
+ .createSingleFieldValue(field.getReference(), computeObjectState(value));
}
/**
@@ -330,7 +330,7 @@
return appView
.abstractValueFactory()
- .createSingleFieldValue(valuesField.field, new EnumValuesObjectState(valuesState));
+ .createSingleFieldValue(valuesField.getReference(), new EnumValuesObjectState(valuesState));
}
private ObjectState computeEnumInstanceObjectState(Value value) {
@@ -428,7 +428,7 @@
return appView
.abstractValueFactory()
- .createSingleFieldValue(enumField.field, computeObjectState(value));
+ .createSingleFieldValue(enumField.getReference(), computeObjectState(value));
}
private ObjectState computeObjectState(Value value) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java
index 65e1ea3..ec51f91 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java
@@ -63,11 +63,13 @@
assert valuesCandidateAbstractValue == null
|| valuesCandidateAbstractValue.equals(value);
valuesCandidateAbstractValue = value;
- enumObjectStateBuilder.put(staticField.field, value.asSingleFieldValue().getState());
+ enumObjectStateBuilder.put(
+ staticField.getReference(), value.asSingleFieldValue().getState());
}
} else if (factory.enumMembers.isEnumField(staticField, staticField.getHolderType())) {
if (value.isSingleFieldValue() && !value.asSingleFieldValue().getState().isEmpty()) {
- enumObjectStateBuilder.put(staticField.field, value.asSingleFieldValue().getState());
+ enumObjectStateBuilder.put(
+ staticField.getReference(), value.asSingleFieldValue().getState());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java
index 64f5bea..f0e63e9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java
@@ -113,7 +113,7 @@
}
DexType enumLiteCandidate = null;
for (DexEncodedMethod virtualMethod : enumLiteMap.virtualMethods()) {
- if (!matchesFindValueByNumberMethod(virtualMethod.method)) {
+ if (!matchesFindValueByNumberMethod(virtualMethod.getReference())) {
return null;
}
if (virtualMethod.returnType() == references.enumLiteType) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
index f15ad69..3cb884a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
@@ -109,7 +109,8 @@
@Override
public boolean isReachableOrReferencedField(
AppInfoWithLiveness appInfo, DexEncodedField field) {
- return !wasRemoved(field.field) && super.isReachableOrReferencedField(appInfo, field);
+ return !wasRemoved(field.getReference())
+ && super.isReachableOrReferencedField(appInfo, field);
}
};
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
index c5f72a3..da0ed41 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
@@ -440,9 +440,9 @@
if (clazz != null) {
DexEncodedMethod newBuilderMethod =
clazz.lookupDirectMethod(
- method -> method.method.name == references.newBuilderMethodName);
+ method -> method.getReference().name == references.newBuilderMethodName);
if (newBuilderMethod != null) {
- bypassClinitforInlining.add(newBuilderMethod.method);
+ bypassClinitforInlining.add(newBuilderMethod.getReference());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnumSwitchMapRemover.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnumSwitchMapRemover.java
index 5c3692c..f8c2bf0 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnumSwitchMapRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnumSwitchMapRemover.java
@@ -64,7 +64,8 @@
return null;
}
ObjectState state =
- enumStaticFieldValues.getObjectStateForPossiblyPinnedField(enumInstanceField.field);
+ enumStaticFieldValues.getObjectStateForPossiblyPinnedField(
+ enumInstanceField.getReference());
if (state == null) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
index b25f946..030fe3d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
@@ -147,7 +147,7 @@
}
public boolean isDynamicMethod(DexEncodedMethod encodedMethod) {
- return isDynamicMethod(encodedMethod.method);
+ return isDynamicMethod(encodedMethod.getReference());
}
public boolean isDynamicMethod(ProgramMethod method) {
@@ -160,7 +160,7 @@
}
public boolean isDynamicMethodBridge(DexEncodedMethod method) {
- return isDynamicMethodBridge(method.method);
+ return isDynamicMethodBridge(method.getReference());
}
public boolean isDynamicMethodBridge(ProgramMethod method) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/NonEmptyObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/NonEmptyObjectState.java
index 6aacc3d..567449e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/NonEmptyObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/NonEmptyObjectState.java
@@ -31,7 +31,7 @@
@Override
public AbstractValue getAbstractFieldValue(DexEncodedField field) {
- return state.getOrDefault(field.field, UnknownValue.getInstance());
+ return state.getOrDefault(field.getReference(), UnknownValue.getInstance());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java
index 4db63a6..012a204 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java
@@ -70,8 +70,8 @@
public void recordFieldHasValue(DexEncodedField field, AbstractValue abstractValue) {
if (!abstractValue.isUnknown()) {
- assert !state.containsKey(field.field);
- state.put(field.field, abstractValue);
+ assert !state.containsKey(field.getReference());
+ state.put(field.getReference(), abstractValue);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
index fa42fcd..6c773a6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
@@ -113,7 +113,7 @@
// Only check for <clinit> side effects if there is no -assumenosideeffects rule.
if (appView.appInfo().hasLiveness()) {
AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
- if (appInfoWithLiveness.noSideEffects.containsKey(resolvedField.field)) {
+ if (appInfoWithLiveness.noSideEffects.containsKey(resolvedField.getReference())) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 506e8af..202df23 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -973,7 +973,7 @@
|| !v.hasDebugUsers()
|| v.debugUsers().stream().anyMatch(i -> !i.isAssume())
|| v.numberOfPhiUsers() > 0
- : StringUtils.join(v.uniqueUsers(), System.lineSeparator());
+ : StringUtils.join(System.lineSeparator(), v.uniqueUsers());
return true;
};
return verifySSATypeLattice(wrapSSAVerifierWithStackValueHandling(verifyValue));
@@ -1091,7 +1091,7 @@
}
}
assert arguments.size()
- == method().method.getArity()
+ == method().getReference().getArity()
+ ((method().accessFlags.isStatic() || ignoreReceiver) ? 0 : 1);
return arguments;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 39f2aee..ae02e8b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -185,7 +185,7 @@
.appInfo()
.resolveMethodOnClass(dexItemFactory.objectMembers.finalize, clazz);
if (finalizeResolutionResult.isSingleResolution()) {
- DexMethod finalizeMethod = finalizeResolutionResult.getSingleTarget().method;
+ DexMethod finalizeMethod = finalizeResolutionResult.getSingleTarget().getReference();
if (finalizeMethod != dexItemFactory.enumMembers.finalize
&& finalizeMethod != dexItemFactory.objectMembers.finalize) {
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index 1017f53..9b68a81 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -111,7 +111,7 @@
boolean isDeadProtoExtensionField =
appView.withGeneratedExtensionRegistryShrinker(
- shrinker -> shrinker.isDeadProtoExtensionField(encodedField.field), false);
+ shrinker -> shrinker.isDeadProtoExtensionField(encodedField.getReference()), false);
if (isDeadProtoExtensionField) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java
index e6f7cb6..4be3d83 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilder.java
@@ -38,7 +38,7 @@
boolean verifyAllMethodsWithCodeExists() {
for (DexProgramClass clazz : appView.appInfo().classes()) {
for (DexEncodedMethod method : clazz.methods()) {
- assert method.hasCode() == (nodes.get(method.method) != null);
+ assert method.hasCode() == (nodes.get(method.getReference()) != null);
}
}
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
index 967fee0..32be662 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
@@ -195,7 +195,7 @@
private void processInvokeWithDynamicDispatch(
Invoke.Type type, DexEncodedMethod encodedTarget, ProgramMethod context) {
- DexMethod target = encodedTarget.method;
+ DexMethod target = encodedTarget.getReference();
DexClass clazz = appView.definitionFor(target.holder);
if (clazz == null) {
assert false : "Unable to lookup holder of `" + target.toSourceString() + "`";
@@ -258,7 +258,7 @@
}
DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
- if (encodedField == null || appView.appInfo().isPinned(encodedField.field)) {
+ if (encodedField == null || appView.appInfo().isPinned(encodedField.getReference())) {
return;
}
@@ -273,7 +273,7 @@
addClassInitializerTarget(clazz);
}
- FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(encodedField.field);
+ FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(encodedField.getReference());
if (fieldAccessInfo != null && fieldAccessInfo.hasKnownWriteContexts()) {
if (fieldAccessInfo.getNumberOfWriteContexts() == 1) {
fieldAccessInfo.forEachWriteContext(this::addFieldReadEdge);
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 8a63d63..682ca02 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
@@ -187,7 +187,7 @@
public DexField resolveField(DexField field) {
DexEncodedField resolvedField =
appView.appInfoForDesugaring().resolveField(field).getResolvedField();
- return resolvedField == null ? field : resolvedField.field;
+ return resolvedField == null ? field : resolvedField.getReference();
}
private void computeInitializers() {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java
index bb8e12a..4ba4555 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/D8MethodProcessor.java
@@ -95,6 +95,9 @@
// The non-synthetic holder is not scheduled. It will be processed once holder is scheduled.
return;
}
+ if (method.getDefinition().isAbstract()) {
+ return;
+ }
terminalFutures.add(
ThreadUtils.processAsynchronously(
() ->
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 93c61ab..e6bc084 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -542,7 +542,7 @@
}
int originalNumberOfArguments =
- method.method.proto.parameters.values.length
+ method.getReference().proto.parameters.values.length
+ argumentsInfo.numberOfRemovedArguments()
+ (method.isStatic() ? 0 : 1)
- prototypeChanges.numberOfExtraParameters();
@@ -562,14 +562,14 @@
DexType argType;
if (argumentInfo.isRewrittenTypeInfo()) {
RewrittenTypeInfo argumentRewrittenTypeInfo = argumentInfo.asRewrittenTypeInfo();
- assert method.method.proto.getParameter(usedArgumentIndex)
+ assert method.getReference().proto.getParameter(usedArgumentIndex)
== argumentRewrittenTypeInfo.getNewType();
// The old type is used to prevent that a changed value from reference to primitive
// type breaks IR building. Rewriting from the old to the new type will be done in the
// IRConverter (typically through the lensCodeRewriter).
argType = argumentRewrittenTypeInfo.getOldType();
} else {
- argType = method.method.proto.getParameter(usedArgumentIndex);
+ argType = method.getReference().proto.getParameter(usedArgumentIndex);
}
usedArgumentIndex++;
writeCallback.accept(register, argType);
@@ -585,7 +585,7 @@
}
for (ExtraParameter extraParameter : prototypeChanges.getExtraParameters()) {
- DexType argType = method.method.proto.getParameter(usedArgumentIndex);
+ DexType argType = method.getReference().proto.getParameter(usedArgumentIndex);
TypeElement type = extraParameter.getTypeElement(appView, argType);
register += type.requiredRegisters();
usedArgumentIndex++;
@@ -1827,7 +1827,7 @@
public void addReturn(int value) {
DexType returnType = method.getDefinition().returnType();
if (returnType.isVoidType()) {
- assert prototypeChanges.hasBeenChangedToReturnVoid(appView);
+ assert prototypeChanges.hasBeenChangedToReturnVoid(appView.dexItemFactory());
addReturn();
} else {
ValueTypeConstraint returnTypeConstraint =
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 54b0a66..0530046 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
@@ -1196,7 +1196,7 @@
+ ExceptionUtils.getMainStackTrace();
assert !method.isProcessed()
|| !appView.enableWholeProgramOptimizations()
- || !appView.appInfo().withLiveness().isNeverReprocessMethod(method.method)
+ || !appView.appInfo().withLiveness().isNeverReprocessMethod(method.getReference())
: "Illegal reprocessing due to -neverreprocess rule: " + context.toSourceString();
if (typeChecker != null && !typeChecker.check(code)) {
@@ -1621,7 +1621,7 @@
timing.end();
}
- if (appView.appInfo().withLiveness().isPinned(code.method().method)) {
+ if (appView.appInfo().withLiveness().isPinned(code.method().getReference())) {
return;
}
@@ -1785,7 +1785,7 @@
return;
}
// Only constructors with certain signatures.
- DexTypeList paramTypes = code.method().method.proto.parameters;
+ DexTypeList paramTypes = code.method().getReference().proto.parameters;
if (paramTypes.size() != 3 ||
paramTypes.values[0] != options.itemFactory.doubleType ||
paramTypes.values[1] != options.itemFactory.doubleType ||
@@ -1967,7 +1967,7 @@
printer.end("cfg");
}
if (options.extensiveLoggingFilter.size() > 0
- && options.extensiveLoggingFilter.contains(code.method().method.toSourceString())) {
+ && options.extensiveLoggingFilter.contains(code.method().getReference().toSourceString())) {
String current = code.toString();
System.out.println();
System.out.println("-----------------------------------------------------------------------");
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 b6609b8..66e7ff7 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
@@ -280,7 +280,7 @@
}
ConstInstruction constantReturnMaterializingInstruction = null;
- if (prototypeChanges.hasBeenChangedToReturnVoid(appView)
+ if (prototypeChanges.hasBeenChangedToReturnVoid(appView.dexItemFactory())
&& invoke.outValue() != null) {
constantReturnMaterializingInstruction =
prototypeChanges.getConstantReturn(code, invoke.getPosition());
@@ -297,7 +297,7 @@
}
Value newOutValue =
- prototypeChanges.hasBeenChangedToReturnVoid(appView)
+ prototypeChanges.hasBeenChangedToReturnVoid(appView.dexItemFactory())
? null
: makeOutValue(invoke, code);
@@ -596,7 +596,7 @@
if (ret.isReturnVoid()) {
break;
}
- DexType returnType = code.method().method.proto.returnType;
+ DexType returnType = code.method().getReference().proto.returnType;
Value retValue = ret.returnValue();
DexType initialType =
retValue.getType().isPrimitiveType()
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
index 4c073e1..d9f8625 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
@@ -152,7 +152,7 @@
+ ", its imprecise type is: "
+ stillImprecise.get(0).getType(),
code.origin,
- new MethodPosition(code.method().method.asMethodReference())));
+ new MethodPosition(code.method().getReference().asMethodReference())));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 5cd32f2..2fc5c3a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -1059,10 +1059,15 @@
factory.intType);
DexMethod method = factory.createMethod(type, proto, name);
addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::IntegerMethods_parseIntSubsequenceWithRadix,
- "parseIntSubsequenceWithRadix"));
+ appView.options().canParseNumbersWithPlusPrefix()
+ ? new MethodGenerator(
+ method,
+ BackportedMethods::IntegerMethods_parseIntSubsequenceWithRadix,
+ "parseIntSubsequenceWithRadix")
+ : new MethodGenerator(
+ method,
+ BackportedMethods::IntegerMethods_parseIntSubsequenceWithRadixDalvik,
+ "parseIntSubsequenceWithRadix"));
// Long
type = factory.boxedLongType;
@@ -1077,10 +1082,15 @@
factory.intType);
method = factory.createMethod(type, proto, name);
addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::LongMethods_parseLongSubsequenceWithRadix,
- "parseLongSubsequenceWithRadix"));
+ appView.options().canParseNumbersWithPlusPrefix()
+ ? new MethodGenerator(
+ method,
+ BackportedMethods::LongMethods_parseLongSubsequenceWithRadix,
+ "parseLongSubsequenceWithRadix")
+ : new MethodGenerator(
+ method,
+ BackportedMethods::LongMethods_parseLongSubsequenceWithRadixDalvik,
+ "parseLongSubsequenceWithRadix"));
// long Long.parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix)
name = factory.createString("parseUnsignedLong");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfClassDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfClassDesugaringEventConsumer.java
index d5acaa7..9b02ab5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfClassDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfClassDesugaringEventConsumer.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.ir.desugar;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.D8MethodProcessor;
public abstract class CfClassDesugaringEventConsumer implements RecordDesugaringEventConsumer {
@@ -25,6 +26,11 @@
public void acceptRecordClass(DexProgramClass recordClass) {
methodProcessor.scheduleDesugaredMethodsForProcessing(recordClass.programMethods());
}
+
+ @Override
+ public void acceptRecordMethod(ProgramMethod method) {
+ assert false;
+ }
}
// TODO(b/): Implement R8CfClassDesugaringEventConsumer
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
index a95569e..a0c4c64 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
@@ -64,6 +64,11 @@
}
@Override
+ public void acceptRecordMethod(ProgramMethod method) {
+ assert false;
+ }
+
+ @Override
public void acceptBackportedMethod(ProgramMethod backportedMethod, ProgramMethod context) {
assert false;
}
@@ -119,6 +124,11 @@
}
@Override
+ public void acceptRecordMethod(ProgramMethod method) {
+ methodProcessor.scheduleDesugaredMethodForProcessing(method);
+ }
+
+ @Override
public void acceptInvokeSpecialBridgeInfo(InvokeSpecialBridgeInfo info) {
synchronized (pendingInvokeSpecialBridges) {
assert !pendingInvokeSpecialBridges.containsKey(info.getNewDirectMethod().getReference());
@@ -242,6 +252,11 @@
}
@Override
+ public void acceptRecordMethod(ProgramMethod method) {
+ assert false : "TODO(b/179146128): To be implemented";
+ }
+
+ @Override
public void acceptBackportedMethod(ProgramMethod backportedMethod, ProgramMethod context) {
// Intentionally empty. The backported method will be hit by the tracing in R8 as if it was
// present in the input code, and thus nothing needs to be done.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 6200603..6ef420d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -27,6 +27,7 @@
import com.android.tools.r8.ir.synthetic.ExceptionThrowingSourceCode;
import com.android.tools.r8.ir.synthetic.SynthesizedCode;
import com.android.tools.r8.position.MethodPosition;
+import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.WorkList;
@@ -125,7 +126,7 @@
ClassInfo parent,
ImmutableList<DexClassAndMethod> forwardedMethodTargets,
EmulatedInterfaceInfo emulatedInterfaceInfo) {
- return forwardedMethodTargets.isEmpty()
+ return forwardedMethodTargets.isEmpty() && emulatedInterfaceInfo.isEmpty()
? parent
: new ClassInfo(parent, forwardedMethodTargets, emulatedInterfaceInfo);
}
@@ -204,6 +205,40 @@
}
}
+ // Emulated interfaces together with the generic signatures.
+ static class EmulatedInterfaces {
+ static EmulatedInterfaces EMPTY = new EmulatedInterfaces(ImmutableSet.of());
+
+ final Set<DexType> emulatedInterfaces;
+
+ EmulatedInterfaces(DexType emulatedInterface) {
+ this.emulatedInterfaces = ImmutableSet.of(emulatedInterface);
+ }
+
+ private EmulatedInterfaces(Set<DexType> emulatedInterfaces) {
+ this.emulatedInterfaces = emulatedInterfaces;
+ }
+
+ boolean isEmpty() {
+ return emulatedInterfaces.isEmpty();
+ }
+
+ boolean contains(DexType type) {
+ return emulatedInterfaces.contains(type);
+ }
+
+ Set<DexType> getEmulatedInterfaces() {
+ return emulatedInterfaces;
+ }
+
+ EmulatedInterfaces merge(EmulatedInterfaces other) {
+ ImmutableSet.Builder<DexType> newEmulatedInterfaces = ImmutableSet.builder();
+ newEmulatedInterfaces.addAll(emulatedInterfaces);
+ newEmulatedInterfaces.addAll(other.emulatedInterfaces);
+ return new EmulatedInterfaces(newEmulatedInterfaces.build());
+ }
+ }
+
// List of emulated interfaces and corresponding signatures which may require forwarding methods.
// If one of the signatures has an override, then the class holding the override is required to
// add the forwarding methods for all signatures, and introduce the corresponding emulated
@@ -213,13 +248,13 @@
private static class EmulatedInterfaceInfo {
static final EmulatedInterfaceInfo EMPTY =
- new EmulatedInterfaceInfo(MethodSignatures.EMPTY, ImmutableSet.of());
+ new EmulatedInterfaceInfo(MethodSignatures.EMPTY, EmulatedInterfaces.EMPTY);
final MethodSignatures signatures;
- final ImmutableSet<DexType> emulatedInterfaces;
+ final EmulatedInterfaces emulatedInterfaces;
private EmulatedInterfaceInfo(
- MethodSignatures methodsToForward, ImmutableSet<DexType> emulatedInterfaces) {
+ MethodSignatures methodsToForward, EmulatedInterfaces emulatedInterfaces) {
this.signatures = methodsToForward;
this.emulatedInterfaces = emulatedInterfaces;
}
@@ -231,17 +266,18 @@
if (other.isEmpty()) {
return this;
}
- ImmutableSet.Builder<DexType> newEmulatedInterfaces = ImmutableSet.builder();
- newEmulatedInterfaces.addAll(emulatedInterfaces);
- newEmulatedInterfaces.addAll(other.emulatedInterfaces);
return new EmulatedInterfaceInfo(
- signatures.merge(other.signatures), newEmulatedInterfaces.build());
+ signatures.merge(other.signatures), emulatedInterfaces.merge(other.emulatedInterfaces));
}
public boolean isEmpty() {
assert !emulatedInterfaces.isEmpty() || signatures.isEmpty();
return emulatedInterfaces.isEmpty();
}
+
+ boolean contains(DexType type) {
+ return emulatedInterfaces.contains(type);
+ }
}
// Helper to keep track of the direct active subclass and nearest program subclass for reporting.
@@ -375,7 +411,7 @@
assert needsLibraryInfo();
MethodSignatures signatures = getDefaultMethods(iface);
EmulatedInterfaceInfo emulatedInterfaceInfo =
- new EmulatedInterfaceInfo(signatures, ImmutableSet.of(iface.type));
+ new EmulatedInterfaceInfo(signatures, new EmulatedInterfaces(iface.type));
return interfaceInfo.withEmulatedInterfaceInfo(emulatedInterfaceInfo);
}
@@ -384,7 +420,7 @@
Set<Wrapper<DexMethod>> defaultMethods =
new HashSet<>(iface.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod method : iface.virtualMethods(DexEncodedMethod::isDefaultMethod)) {
- defaultMethods.add(equivalence.wrap(method.method));
+ defaultMethods.add(equivalence.wrap(method.getReference()));
}
return MethodSignatures.create(defaultMethods);
}
@@ -422,14 +458,13 @@
// implement the interface and the emulated one for correct emulated dispatch.
// The class signature won't include the correct type parameters for the duplicated interfaces,
// i.e., there will be foo.A instead of foo.A<K,V>, but such parameters are unused.
- private void duplicateEmulatedInterfaces(
- DexClass clazz, ImmutableSet<DexType> emulatedInterfaces) {
+ private void duplicateEmulatedInterfaces(DexClass clazz, EmulatedInterfaces emulatedInterfaces) {
if (clazz.isNotProgramClass()) {
return;
}
- Set<DexType> filtered = new HashSet<>(emulatedInterfaces);
+ Set<DexType> filtered = new HashSet<>(emulatedInterfaces.getEmulatedInterfaces());
WorkList<DexType> workList = WorkList.newIdentityWorkList();
- for (DexType emulatedInterface : emulatedInterfaces) {
+ for (DexType emulatedInterface : emulatedInterfaces.getEmulatedInterfaces()) {
DexClass iface = appView.definitionFor(emulatedInterface);
if (iface != null) {
assert iface.isLibraryClass()
@@ -447,7 +482,7 @@
workList.addIfNotSeen(iface.getInterfaces());
}
- for (DexType emulatedInterface : emulatedInterfaces) {
+ for (DexType emulatedInterface : emulatedInterfaces.getEmulatedInterfaces()) {
DexClass s = appView.definitionFor(emulatedInterface);
if (s != null) {
s = appView.definitionFor(s.superType);
@@ -458,13 +493,17 @@
}
}
+ // Collect the signatures for the emulated interfaces to add.
+ Map<DexType, GenericSignature.ClassTypeSignature> signatures = new IdentityHashMap<>();
+ collectEmulatedInterfaces(clazz, filtered, signatures);
// We need to introduce them in deterministic order for deterministic compilation.
ArrayList<DexType> sortedEmulatedInterfaces = new ArrayList<>(filtered);
Collections.sort(sortedEmulatedInterfaces);
List<GenericSignature.ClassTypeSignature> extraInterfaceSignatures = new ArrayList<>();
for (DexType extraInterface : sortedEmulatedInterfaces) {
- extraInterfaceSignatures.add(
- new GenericSignature.ClassTypeSignature(rewriter.getEmulatedInterface(extraInterface)));
+ GenericSignature.ClassTypeSignature signature = signatures.get(extraInterface);
+ assert signature != null;
+ extraInterfaceSignatures.add(signature);
}
// The emulated interface might already be implemented if the input class has gone through
// library desugaring already.
@@ -489,6 +528,75 @@
clazz.asProgramClass().addExtraInterfaces(extraInterfaceSignatures);
}
+ private void collectEmulatedInterfaces(
+ DexClass clazz,
+ Set<DexType> emulatesInterfaces,
+ Map<DexType, GenericSignature.ClassTypeSignature> extraInterfaceSignatures) {
+ // TODO(b/182329331): Only handle type arguments for Cf to Cf desugar.
+ if (appView.options().cfToCfDesugar && clazz.validInterfaceSignatures()) {
+ clazz.forEachImmediateSupertype(
+ (type, signature) -> {
+ if (emulatesInterfaces.contains(type)) {
+ extraInterfaceSignatures.put(
+ type,
+ new GenericSignature.ClassTypeSignature(
+ rewriter.getEmulatedInterface(type), signature.typeArguments()));
+ }
+ collectEmulatedInterfacesWithPropagatedTypeArguments(
+ type, signature.typeArguments(), emulatesInterfaces, extraInterfaceSignatures);
+ });
+ } else {
+ clazz.forEachImmediateSupertype(
+ (type) -> {
+ if (emulatesInterfaces.contains(type)) {
+ extraInterfaceSignatures.put(
+ type,
+ new GenericSignature.ClassTypeSignature(rewriter.getEmulatedInterface(type)));
+ }
+ collectEmulatedInterfacesWithPropagatedTypeArguments(
+ type, null, emulatesInterfaces, extraInterfaceSignatures);
+ });
+ }
+ }
+
+ private void collectEmulatedInterfacesWithPropagatedTypeArguments(
+ DexType type,
+ List<GenericSignature.FieldTypeSignature> typeArguments,
+ Set<DexType> emulatesInterfaces,
+ Map<DexType, GenericSignature.ClassTypeSignature> extraInterfaceSignatures) {
+ DexClass clazz = appView.definitionFor(type);
+ if (clazz == null) {
+ return;
+ }
+ // TODO(b/182329331): Only handle type arguments for Cf to Cf desugar.
+ if (appView.options().cfToCfDesugar && clazz.validInterfaceSignatures()) {
+ assert typeArguments != null;
+ clazz.forEachImmediateSupertypeWithAppliedTypeArguments(
+ typeArguments,
+ (iface, signature) -> {
+ if (emulatesInterfaces.contains(iface)) {
+ extraInterfaceSignatures.put(
+ iface,
+ new GenericSignature.ClassTypeSignature(
+ rewriter.getEmulatedInterface(iface), signature));
+ }
+ collectEmulatedInterfacesWithPropagatedTypeArguments(
+ iface, signature, emulatesInterfaces, extraInterfaceSignatures);
+ });
+ } else {
+ assert typeArguments == null;
+ clazz.forEachImmediateSupertype(
+ iface -> {
+ if (emulatesInterfaces.contains(iface)) {
+ extraInterfaceSignatures.put(
+ iface,
+ new GenericSignature.ClassTypeSignature(rewriter.getEmulatedInterface(iface)));
+ }
+ collectEmulatedInterfacesWithPropagatedTypeArguments(
+ iface, null, emulatesInterfaces, extraInterfaceSignatures);
+ });
+ }
+ }
// If any of the signature would lead to a different behavior than the default method on the
// emulated interface, we need to resolve the forwarding methods.
private boolean shouldResolveForwardingMethodsForEmulatedInterfaces(
@@ -501,7 +609,7 @@
}
DexClass resolvedHolder = resolutionResult.asSingleResolution().getResolvedHolder();
if (!resolvedHolder.isLibraryClass()
- && !emulatedInterfaceInfo.emulatedInterfaces.contains(resolvedHolder.type)) {
+ && !emulatedInterfaceInfo.contains(resolvedHolder.type)) {
return true;
}
}
@@ -533,27 +641,44 @@
// the 'addForward' call-back is called with the target of the forward.
private void resolveForwardForSignature(
DexClass clazz, DexMethod method, Consumer<DexClassAndMethod> addForward) {
- // Resolve the default method with base type as the symbolic holder as call sites are not known.
- // The dispatch target is then looked up from the possible "instance" class.
- // Doing so can cause an invalid invoke to become valid (at runtime resolution at a subtype
- // might have failed which is hidden by the insertion of the forward method). However, not doing
- // so could cause valid dispatches to become invalid by resolving to private overrides.
AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
- DexClassAndMethod virtualDispatchTarget =
- appInfo
- .resolveMethodOnInterface(method.holder, method)
- .lookupVirtualDispatchTarget(clazz, appInfo);
- if (virtualDispatchTarget == null) {
- // If no target is found due to multiple default method targets, preserve ICCE behavior.
- ResolutionResult resolutionFromSubclass = appInfo.resolveMethodOn(clazz, method);
- if (resolutionFromSubclass.isIncompatibleClassChangeErrorResult()) {
- addICCEThrowingMethod(method, clazz);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(clazz, method);
+ if (resolutionResult.isFailedResolution()
+ || resolutionResult.asSuccessfulMemberResolutionResult().getResolvedMember().isStatic()) {
+ // When doing resolution we may find a static or private targets and bubble up the failed
+ // resolution to preserve ICCE even though the resolution actually succeeded, ie. finding a
+ // method with the same name and descriptor. For invoke-virtual and invoke-interface, the
+ // selected method will only consider instance methods.
+ BooleanBox staticTarget = new BooleanBox(true);
+ if (resolutionResult.isFailedResolution()) {
+ resolutionResult
+ .asFailedResolution()
+ .forEachFailureDependency(target -> staticTarget.and(target.isStatic()));
+ } else if (resolutionResult.isSuccessfulMemberResolutionResult()) {
+ staticTarget.set(
+ resolutionResult.asSuccessfulMemberResolutionResult().getResolvedMember().isStatic());
+ }
+ if (staticTarget.isAssigned() && staticTarget.isTrue()) {
+ resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ }
+ if (resolutionResult.isFailedResolution()) {
+ if (resolutionResult.isIncompatibleClassChangeErrorResult()) {
+ addICCEThrowingMethod(method, clazz);
+ return;
+ }
+ if (resolutionResult.isNoSuchMethodErrorResult(clazz, appInfo)) {
+ addNoSuchMethodErrorThrowingMethod(method, clazz);
+ return;
+ }
+ assert resolutionResult.isIllegalAccessErrorResult(clazz, appInfo);
+ addIllegalAccessErrorThrowingMethod(method, clazz);
return;
}
- assert resolutionFromSubclass.isFailedResolution()
- || resolutionFromSubclass.getSingleTarget().isPrivateMethod();
- return;
}
+ assert resolutionResult.isSuccessfulMemberResolutionResult();
+ DexClassAndMethod virtualDispatchTarget =
+ resolutionResult.lookupVirtualDispatchTarget(clazz, appInfo);
+ assert virtualDispatchTarget != null;
// Don't forward if the target is explicitly marked as 'dont-rewrite'
if (dontRewrite(virtualDispatchTarget)) {
@@ -612,6 +737,18 @@
}
private void addICCEThrowingMethod(DexMethod method, DexClass clazz) {
+ addThrowingMethod(method, clazz, dexItemFactory.icceType);
+ }
+
+ private void addIllegalAccessErrorThrowingMethod(DexMethod method, DexClass clazz) {
+ addThrowingMethod(method, clazz, dexItemFactory.illegalAccessErrorType);
+ }
+
+ private void addNoSuchMethodErrorThrowingMethod(DexMethod method, DexClass clazz) {
+ addThrowingMethod(method, clazz, dexItemFactory.noSuchMethodErrorType);
+ }
+
+ private void addThrowingMethod(DexMethod method, DexClass clazz, DexType errorType) {
if (!clazz.isProgramClass()) {
return;
}
@@ -625,8 +762,7 @@
ParameterAnnotationsList.empty(),
new SynthesizedCode(
callerPosition ->
- new ExceptionThrowingSourceCode(
- clazz.type, method, callerPosition, dexItemFactory.icceType)),
+ new ExceptionThrowingSourceCode(clazz.type, method, callerPosition, errorType)),
true);
addSyntheticMethod(clazz.asProgramClass(), newEncodedMethod);
}
@@ -644,7 +780,7 @@
"Attempt to add forwarding method that conflicts with existing method.",
null,
clazz.getOrigin(),
- new MethodPosition(methodOnSelf.method.asMethodReference()));
+ new MethodPosition(methodOnSelf.getReference().asMethodReference()));
}
// NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
@@ -696,8 +832,8 @@
SignaturesInfo signatures = visitLibraryClassInfo(clazz.superType);
// The class may inherit emulated interface info from its program superclass if the latter
// did not require to resolve the forwarding methods for emualted interfaces.
- signatures = signatures.withEmulatedInterfaceInfo(superInfo.emulatedInterfaceInfo);
assert superInfo.isEmpty() || signatures.isEmpty();
+ signatures = signatures.withEmulatedInterfaceInfo(superInfo.emulatedInterfaceInfo);
for (DexType iface : clazz.interfaces.values) {
signatures = signatures.merge(visitInterfaceInfo(iface, thisContext));
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
index fd4abda..5760bd2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
@@ -267,7 +267,7 @@
private static boolean hasVirtualMethodWithSignature(DexClass clazz, DexEncodedMethod method) {
for (DexEncodedMethod existingMethod : clazz.virtualMethods()) {
- if (existingMethod.method.equals(method.method)) {
+ if (existingMethod.getReference().equals(method.getReference())) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DefaultMethodsHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/DefaultMethodsHelper.java
index 07277bc..838374d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DefaultMethodsHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DefaultMethodsHelper.java
@@ -44,7 +44,7 @@
DexMethod getSingleCandidate(DexMethod method) {
DexMethod candidate = null;
for (DexEncodedMethod encodedMethod : live) {
- DexMethod current = encodedMethod.method;
+ DexMethod current = encodedMethod.getReference();
if (current.proto == method.proto && current.name == method.name) {
if (candidate != null) {
return null;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
index f2f255a..4f05b2e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
@@ -341,10 +341,10 @@
private ProgramMethod generateCallbackMethod(
DexEncodedMethod originalMethod, DexProgramClass clazz) {
DexMethod methodToInstall =
- methodWithVivifiedTypeInSignature(originalMethod.method, clazz.type, appView);
+ methodWithVivifiedTypeInSignature(originalMethod.getReference(), clazz.type, appView);
CfCode cfCode =
new APIConverterWrapperCfCodeProvider(
- appView, originalMethod.method, null, this, clazz.isInterface())
+ appView, originalMethod.getReference(), null, this, clazz.isInterface())
.generateCfCode();
DexEncodedMethod newMethod =
wrapperSynthesizor.newSynthesizedMethod(methodToInstall, originalMethod, cfCode);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
index 8a6624e..4f4673a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -264,7 +264,7 @@
if (!appView.options().encodeChecksums) {
return DexProgramClass::invalidChecksumRequest;
}
- return c -> method.method.hashCode();
+ return c -> method.getReference().hashCode();
}
// Used by the ListOfBackportedMethods utility.
@@ -331,7 +331,7 @@
}
DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
assert singleTarget != null;
- retarget = getRetargetLibraryMember(singleTarget.method);
+ retarget = getRetargetLibraryMember(singleTarget.getReference());
}
return retarget;
}
@@ -622,7 +622,8 @@
// Dispatch holder.
DexType holderType = dispatchHolderTypeFor(emulatedDispatchMethod);
DexEncodedMethod dispatchMethod =
- generateHolderDispatchMethod(emulatedDispatchMethod, holderType, itfMethod.method);
+ generateHolderDispatchMethod(
+ emulatedDispatchMethod, holderType, itfMethod.getReference());
synthesizeClassWithUniqueMethod(
builder,
holderAccessFlags,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index ce4f61a..f5845d4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -239,7 +239,9 @@
DexAnnotationSet.empty(),
DexEncodedField.EMPTY_ARRAY, // No static fields.
new DexEncodedField[] {wrapperField},
- new DexEncodedMethod[] {synthesizeConstructor(wrapperField.field), conversionMethod},
+ new DexEncodedMethod[] {
+ synthesizeConstructor(wrapperField.getReference()), conversionMethod
+ },
virtualMethods,
factory.getSkipNameValidationForTesting(),
DexProgramClass::checksumFromType);
@@ -275,21 +277,17 @@
DexMethod methodToInstall =
factory.createMethod(
wrapperField.getHolderType(),
- dexEncodedMethod.method.proto,
- dexEncodedMethod.method.name);
+ dexEncodedMethod.getReference().proto,
+ dexEncodedMethod.getReference().name);
CfCode cfCode;
if (dexEncodedMethod.isFinal()) {
invalidWrappers.add(wrapperField.getHolderType());
- finalMethods.add(dexEncodedMethod.method);
+ finalMethods.add(dexEncodedMethod.getReference());
continue;
} else {
cfCode =
new APIConverterVivifiedWrapperCfCodeProvider(
- appView,
- methodToInstall,
- wrapperField.field,
- converter,
- isInterface)
+ appView, methodToInstall, wrapperField.getReference(), converter, isInterface)
.generateCfCode();
}
DexEncodedMethod newDexEncodedMethod =
@@ -320,16 +318,20 @@
boolean isInterface = holderClass == null || holderClass.isInterface();
DexMethod methodToInstall =
DesugaredLibraryAPIConverter.methodWithVivifiedTypeInSignature(
- dexEncodedMethod.method, wrapperField.getHolderType(), appView);
+ dexEncodedMethod.getReference(), wrapperField.getHolderType(), appView);
CfCode cfCode;
if (dexEncodedMethod.isFinal()) {
invalidWrappers.add(wrapperField.getHolderType());
- finalMethods.add(dexEncodedMethod.method);
+ finalMethods.add(dexEncodedMethod.getReference());
continue;
} else {
cfCode =
new APIConverterWrapperCfCodeProvider(
- appView, dexEncodedMethod.method, wrapperField.field, converter, isInterface)
+ appView,
+ dexEncodedMethod.getReference(),
+ wrapperField.getReference(),
+ converter,
+ isInterface)
.generateCfCode();
}
DexEncodedMethod newDexEncodedMethod =
@@ -398,7 +400,7 @@
// This looks quadratic but given the size of the collections met in practice for
// desugared libraries (Max ~15) it does not matter.
for (DexEncodedMethod alreadyImplementedMethod : implementedMethods) {
- if (alreadyImplementedMethod.method.match(virtualMethod.method)) {
+ if (alreadyImplementedMethod.getReference().match(virtualMethod.getReference())) {
alreadyAdded = true;
break;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index a1c0d58..f6a653b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -198,8 +198,10 @@
clazz.forEachMethod(
m -> {
if (m.isDefaultMethod()) {
- appInfo.dexItemFactory().registerTypeNeededForDesugaring(m.method.proto.returnType);
- for (DexType param : m.method.proto.parameters.values) {
+ appInfo
+ .dexItemFactory()
+ .registerTypeNeededForDesugaring(m.getReference().proto.returnType);
+ for (DexType param : m.getReference().proto.parameters.values) {
appInfo.dexItemFactory().registerTypeNeededForDesugaring(param);
}
}
@@ -216,7 +218,7 @@
if (emulatedInterfaceClass != null) {
for (DexEncodedMethod encodedMethod :
emulatedInterfaceClass.methods(DexEncodedMethod::isDefaultMethod)) {
- emulatedMethods.add(encodedMethod.method.name);
+ emulatedMethods.add(encodedMethod.getReference().name);
}
}
}
@@ -1243,8 +1245,7 @@
InterfaceProcessorNestedGraphLens.builder();
Map<DexClass, DexProgramClass> classMapping =
processInterfaces(builder, flavour, graphLensBuilder, synthesizedMethods::add);
- InterfaceProcessorNestedGraphLens graphLens =
- graphLensBuilder.build(appView.dexItemFactory(), appView.graphLens());
+ InterfaceProcessorNestedGraphLens graphLens = graphLensBuilder.build(appView);
if (appView.enableWholeProgramOptimizations() && graphLens != null) {
appView.setGraphLens(graphLens);
}
@@ -1476,7 +1477,7 @@
// Hide by virtual methods of this interface.
for (DexEncodedMethod virtual : definedInterface.virtualMethods()) {
- helper.hideMatches(virtual.method);
+ helper.hideMatches(virtual.getReference());
}
// Add all default methods of this interface.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriterFixup.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriterFixup.java
index ed8077a..bb0de67 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriterFixup.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriterFixup.java
@@ -53,8 +53,7 @@
return null;
}
// Map default methods to their companion methods.
- DexMethod mappedMethod =
- graphLens.getExtraOriginalMethodSignatures().getRepresentativeKey(method);
+ DexMethod mappedMethod = graphLens.getExtraNewMethodSignatures().getRepresentativeValue(method);
if (mappedMethod != null) {
return mappedMethod;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index d20eee7..0199730 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -37,9 +37,9 @@
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.GraphLens;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodCollection;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Invoke.Type;
@@ -256,7 +256,8 @@
implMethod.copyMetadata(virtual);
virtual.setDefaultInterfaceMethodImplementation(implMethod);
companionMethods.add(implMethod);
- graphLensBuilder.recordCodeMovedToCompanionClass(method.getReference(), implMethod.method);
+ graphLensBuilder.recordCodeMovedToCompanionClass(
+ method.getReference(), implMethod.getReference());
}
// Remove bridge methods.
@@ -324,7 +325,8 @@
newFlags.promoteToStatic();
DexMethod companionMethod =
- rewriter.privateAsMethodOfCompanionClass(oldMethod, appView.dexItemFactory());
+ InterfaceMethodRewriter.privateAsMethodOfCompanionClass(
+ oldMethod, appView.dexItemFactory());
Code code = definition.getCode();
if (code == null) {
@@ -397,7 +399,7 @@
// also be kept (such a situation can happen if the vertical class merger merges two interfaces).
private boolean interfaceMethodRemovalChangesApi(DexEncodedMethod method, DexClass iface) {
if (appView.enableWholeProgramOptimizations()) {
- if (appView.appInfo().withLiveness().isPinned(method.method)) {
+ if (appView.appInfo().withLiveness().isPinned(method.getReference())) {
return true;
}
}
@@ -411,7 +413,7 @@
if (clazz == null || !seenBefore.add(clazz.type)) {
continue;
}
- if (clazz.lookupVirtualMethod(method.method) != null) {
+ if (clazz.lookupVirtualMethod(method.getReference()) != null) {
return false;
}
addSuperTypes(clazz, worklist);
@@ -433,32 +435,24 @@
if (method.accessFlags.isNative()) {
throw new Unimplemented("Native interface methods are not yet supported.");
}
- return method.accessFlags.isStatic() && !rewriter.factory.isClassConstructor(method.method);
+ return method.accessFlags.isStatic()
+ && !rewriter.factory.isClassConstructor(method.getReference());
}
// Specific lens which remaps invocation types to static since all rewrites performed here
// are to static companion methods.
public static class InterfaceProcessorNestedGraphLens extends NestedGraphLens {
- private BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod>
- extraOriginalMethodSignatures;
+ private BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> extraNewMethodSignatures;
public InterfaceProcessorNestedGraphLens(
- Map<DexType, DexType> typeMap,
- Map<DexMethod, DexMethod> methodMap,
+ AppView<?> appView,
BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
- BidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures,
- BidirectionalOneToOneMap<DexMethod, DexMethod> extraOriginalMethodSignatures,
- GraphLens previousLens,
- DexItemFactory dexItemFactory) {
- super(
- typeMap,
- methodMap,
- fieldMap,
- originalMethodSignatures,
- previousLens,
- dexItemFactory);
- this.extraOriginalMethodSignatures = extraOriginalMethodSignatures;
+ BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap,
+ Map<DexType, DexType> typeMap,
+ BidirectionalOneToOneMap<DexMethod, DexMethod> extraNewMethodSignatures) {
+ super(appView, fieldMap, methodMap, typeMap);
+ this.extraNewMethodSignatures = extraNewMethodSignatures;
}
public static InterfaceProcessorNestedGraphLens find(GraphLens lens) {
@@ -476,14 +470,14 @@
}
public void toggleMappingToExtraMethods() {
- BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> tmp = originalMethodSignatures;
- this.originalMethodSignatures = extraOriginalMethodSignatures;
- this.extraOriginalMethodSignatures = tmp;
+ BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> tmp = newMethodSignatures;
+ this.newMethodSignatures = extraNewMethodSignatures;
+ this.extraNewMethodSignatures = tmp;
}
public BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod>
- getExtraOriginalMethodSignatures() {
- return extraOriginalMethodSignatures;
+ getExtraNewMethodSignatures() {
+ return extraNewMethodSignatures;
}
@Override
@@ -503,14 +497,14 @@
@Override
protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
- return extraOriginalMethodSignatures.getRepresentativeValueOrDefault(
- method, originalMethodSignatures.getRepresentativeValueOrDefault(method, method));
+ return extraNewMethodSignatures.getRepresentativeKeyOrDefault(
+ method, newMethodSignatures.getRepresentativeKeyOrDefault(method, method));
}
@Override
protected DexMethod internalGetNextMethodSignature(DexMethod method) {
- return originalMethodSignatures.getRepresentativeKeyOrDefault(
- method, extraOriginalMethodSignatures.getRepresentativeKeyOrDefault(method, method));
+ return newMethodSignatures.getRepresentativeValueOrDefault(
+ method, extraNewMethodSignatures.getRepresentativeValueOrDefault(method, method));
}
@Override
@@ -522,33 +516,24 @@
return new Builder();
}
- public static class Builder extends NestedGraphLens.Builder {
+ public static class Builder extends GraphLens.Builder {
- private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod>
- extraOriginalMethodSignatures = new BidirectionalOneToOneHashMap<>();
+ private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> extraNewMethodSignatures =
+ new BidirectionalOneToOneHashMap<>();
public void recordCodeMovedToCompanionClass(DexMethod from, DexMethod to) {
assert from != to;
- originalMethodSignatures.put(from, from);
- extraOriginalMethodSignatures.put(to, from);
+ methodMap.put(from, from);
+ extraNewMethodSignatures.put(from, to);
}
@Override
- public InterfaceProcessorNestedGraphLens build(
- DexItemFactory dexItemFactory, GraphLens previousLens) {
- if (fieldMap.isEmpty()
- && originalMethodSignatures.isEmpty()
- && extraOriginalMethodSignatures.isEmpty()) {
+ public InterfaceProcessorNestedGraphLens build(AppView<?> appView) {
+ if (fieldMap.isEmpty() && methodMap.isEmpty() && extraNewMethodSignatures.isEmpty()) {
return null;
}
return new InterfaceProcessorNestedGraphLens(
- typeMap,
- methodMap,
- fieldMap,
- originalMethodSignatures,
- extraOriginalMethodSignatures,
- previousLens,
- dexItemFactory);
+ appView, fieldMap, methodMap, typeMap, extraNewMethodSignatures);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index d54264c..a264d65 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -575,7 +575,7 @@
true);
newMethod.copyMetadata(encodedMethod);
forcefullyMovedLambdaMethodConsumer.acceptForcefullyMovedLambdaMethod(
- encodedMethod.method, callTarget);
+ encodedMethod.getReference(), callTarget);
DexEncodedMethod.setDebugInfoWithFakeThisParameter(
newMethod.getCode(), callTarget.getArity(), appView);
@@ -659,7 +659,7 @@
true);
newMethod.copyMetadata(encodedMethod);
forcefullyMovedLambdaMethodConsumer.acceptForcefullyMovedLambdaMethod(
- encodedMethod.method, callTarget);
+ encodedMethod.getReference(), callTarget);
return newMethod;
});
if (replacement != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/RecordCfMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/RecordCfMethods.java
new file mode 100644
index 0000000..85a7982
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/RecordCfMethods.java
@@ -0,0 +1,454 @@
+// 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.
+
+// ***********************************************************************************
+// GENERATED FILE. DO NOT EDIT! See GenerateRecordMethods.java.
+// ***********************************************************************************
+
+package com.android.tools.r8.ir.desugar;
+
+import com.android.tools.r8.cf.code.CfArithmeticBinop;
+import com.android.tools.r8.cf.code.CfArrayLength;
+import com.android.tools.r8.cf.code.CfArrayLoad;
+import com.android.tools.r8.cf.code.CfCheckCast;
+import com.android.tools.r8.cf.code.CfConstNumber;
+import com.android.tools.r8.cf.code.CfConstString;
+import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.FrameType;
+import com.android.tools.r8.cf.code.CfGoto;
+import com.android.tools.r8.cf.code.CfIf;
+import com.android.tools.r8.cf.code.CfIfCmp;
+import com.android.tools.r8.cf.code.CfIinc;
+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.CfNew;
+import com.android.tools.r8.cf.code.CfNewArray;
+import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStore;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.MemberType;
+import com.android.tools.r8.ir.code.NumericType;
+import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.ImmutableList;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+
+public final class RecordCfMethods {
+
+ public static void registerSynthesizedCodeReferences(DexItemFactory factory) {
+ factory.createSynthesizedType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;");
+ factory.createSynthesizedType("Ljava/lang/Record;");
+ factory.createSynthesizedType("Ljava/util/Arrays;");
+ factory.createSynthesizedType("[Ljava/lang/Object;");
+ factory.createSynthesizedType("[Ljava/lang/String;");
+ }
+
+ public static CfCode RecordMethods_equals(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ CfLabel label4 = new CfLabel();
+ CfLabel label5 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 2,
+ 2,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.classType),
+ options.itemFactory.createString("getClass")),
+ false),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.classType),
+ options.itemFactory.createString("getClass")),
+ false),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label3),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfCheckCast(options.itemFactory.createType("Ljava/lang/Record;")),
+ label1,
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/Record;"),
+ options.itemFactory.createProto(
+ options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.createString("$record$getFieldsAsObjects")),
+ false),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/Record;"),
+ options.itemFactory.createProto(
+ options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.createString("$record$getFieldsAsObjects")),
+ false),
+ label2,
+ new CfInvoke(
+ 184,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createProto(
+ options.itemFactory.booleanType,
+ options.itemFactory.createType("[Ljava/lang/Object;"),
+ options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.createString("equals")),
+ false),
+ new CfIf(If.Type.EQ, ValueType.INT, label3),
+ new CfConstNumber(1, ValueType.INT),
+ new CfGoto(label4),
+ label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfConstNumber(0, ValueType.INT),
+ label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ new ArrayDeque<>(
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType)))),
+ new CfReturn(ValueType.INT),
+ label5),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode RecordMethods_hashCode(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 2,
+ 1,
+ ImmutableList.of(
+ label0,
+ new CfConstNumber(31, ValueType.INT),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/Record;"),
+ options.itemFactory.createProto(
+ options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.createString("$record$getFieldsAsObjects")),
+ false),
+ new CfInvoke(
+ 184,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createProto(
+ options.itemFactory.intType,
+ options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.createString("hashCode")),
+ false),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.INT),
+ new CfLoad(ValueType.OBJECT, 0),
+ label1,
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.classType),
+ options.itemFactory.createString("getClass")),
+ false),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.intType),
+ options.itemFactory.createString("hashCode")),
+ false),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+ label2,
+ new CfReturn(ValueType.INT),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode RecordMethods_toString(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ CfLabel label4 = new CfLabel();
+ CfLabel label5 = new CfLabel();
+ CfLabel label6 = new CfLabel();
+ CfLabel label7 = new CfLabel();
+ CfLabel label8 = new CfLabel();
+ CfLabel label9 = new CfLabel();
+ CfLabel label10 = new CfLabel();
+ CfLabel label11 = new CfLabel();
+ CfLabel label12 = new CfLabel();
+ CfLabel label13 = new CfLabel();
+ CfLabel label14 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 3,
+ 7,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.booleanType),
+ options.itemFactory.createString("isEmpty")),
+ false),
+ new CfIf(If.Type.EQ, ValueType.INT, label1),
+ new CfConstNumber(0, ValueType.INT),
+ new CfNewArray(options.itemFactory.createType("[Ljava/lang/String;")),
+ new CfGoto(label2),
+ label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.stringType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstString(options.itemFactory.createString(";")),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(
+ options.itemFactory.createType("[Ljava/lang/String;"),
+ options.itemFactory.stringType),
+ options.itemFactory.createString("split")),
+ false),
+ label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.stringType)
+ }),
+ new ArrayDeque<>(
+ Arrays.asList(
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/lang/String;"))))),
+ new CfStore(ValueType.OBJECT, 3),
+ label3,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/Record;"),
+ options.itemFactory.createProto(
+ options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.createString("$record$getFieldsAsObjects")),
+ false),
+ new CfStore(ValueType.OBJECT, 4),
+ label4,
+ new CfNew(options.itemFactory.stringBuilderType),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfInvoke(
+ 183,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
+ options.itemFactory.createString("<init>")),
+ false),
+ new CfStore(ValueType.OBJECT, 5),
+ label5,
+ new CfLoad(ValueType.OBJECT, 5),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfConstString(options.itemFactory.createString("[")),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfStackInstruction(CfStackInstruction.Opcode.Pop),
+ label6,
+ new CfConstNumber(0, ValueType.INT),
+ new CfStore(ValueType.INT, 6),
+ label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5, 6},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/String;")),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfLoad(ValueType.INT, 6),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfArrayLength(),
+ new CfIfCmp(If.Type.GE, ValueType.INT, label12),
+ label8,
+ new CfLoad(ValueType.OBJECT, 5),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfLoad(ValueType.INT, 6),
+ new CfArrayLoad(MemberType.OBJECT),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfConstString(options.itemFactory.createString("=")),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfLoad(ValueType.OBJECT, 4),
+ new CfLoad(ValueType.INT, 6),
+ new CfArrayLoad(MemberType.OBJECT),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.objectType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfStackInstruction(CfStackInstruction.Opcode.Pop),
+ label9,
+ new CfLoad(ValueType.INT, 6),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfArrayLength(),
+ new CfConstNumber(1, ValueType.INT),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+ new CfIfCmp(If.Type.EQ, ValueType.INT, label11),
+ label10,
+ new CfLoad(ValueType.OBJECT, 5),
+ new CfConstString(options.itemFactory.createString(", ")),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfStackInstruction(CfStackInstruction.Opcode.Pop),
+ label11,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5, 6},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/String;")),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfIinc(6, 1),
+ new CfGoto(label7),
+ label12,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;")),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/String;")),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfLoad(ValueType.OBJECT, 5),
+ new CfConstString(options.itemFactory.createString("]")),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
+ options.itemFactory.createString("append")),
+ false),
+ new CfStackInstruction(CfStackInstruction.Opcode.Pop),
+ label13,
+ new CfLoad(ValueType.OBJECT, 5),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
+ options.itemFactory.createString("toString")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label14),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/RecordDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/RecordDesugaringEventConsumer.java
index 19d9ae3..61eb249 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/RecordDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/RecordDesugaringEventConsumer.java
@@ -5,8 +5,11 @@
package com.android.tools.r8.ir.desugar;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramMethod;
public interface RecordDesugaringEventConsumer {
void acceptRecordClass(DexProgramClass recordClass);
+
+ void acceptRecordMethod(ProgramMethod method);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java
index 67e2c90..469f119 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java
@@ -4,50 +4,78 @@
package com.android.tools.r8.ir.desugar;
-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.CfFieldInstruction;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
-import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfInvokeDynamic;
import com.android.tools.r8.cf.code.CfTypeInstruction;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
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.DexMethodHandle;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
+import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.synthetic.CallObjectInitCfCodeProvider;
+import com.android.tools.r8.ir.synthetic.RecordGetFieldsAsObjectsCfCodeProvider;
+import com.android.tools.r8.naming.dexitembasedstring.ClassNameComputationInfo;
import com.android.tools.r8.synthesis.SyntheticNaming;
+import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
+import java.util.function.BiFunction;
+import org.objectweb.asm.Opcodes;
public class RecordRewriter implements CfInstructionDesugaring, CfClassDesugaring {
private final AppView<?> appView;
private final DexItemFactory factory;
+ private final DexProto recordToStringHelperProto;
+ private final DexProto recordEqualsHelperProto;
+ private final DexProto recordHashCodeHelperProto;
+
+ public static final String GET_FIELDS_AS_OBJECTS_METHOD_NAME = "$record$getFieldsAsObjects";
public static RecordRewriter create(AppView<?> appView) {
return appView.options().shouldDesugarRecords() ? new RecordRewriter(appView) : null;
}
+ public static void registerSynthesizedCodeReferences(DexItemFactory factory) {
+ RecordCfMethods.registerSynthesizedCodeReferences(factory);
+ RecordGetFieldsAsObjectsCfCodeProvider.registerSynthesizedCodeReferences(factory);
+ }
+
private RecordRewriter(AppView<?> appView) {
this.appView = appView;
factory = appView.dexItemFactory();
+ recordToStringHelperProto =
+ factory.createProto(
+ factory.stringType, factory.recordType, factory.stringType, factory.stringType);
+ recordEqualsHelperProto =
+ factory.createProto(factory.booleanType, factory.recordType, factory.objectType);
+ recordHashCodeHelperProto = factory.createProto(factory.intType, factory.recordType);
}
public void scan(
@@ -97,41 +125,168 @@
CfInstructionDesugaringEventConsumer eventConsumer,
ProgramMethod context,
MethodProcessingContext methodProcessingContext) {
-
- // TODO(b/179146128): This is a temporary work-around to test desugaring of records
- // without rewriting the record invoke-custom. This should be removed when the record support
- // is complete.
- if (instruction.isInvokeDynamic()
- && context.getHolder().superType == factory.recordType
- && (context.getReference().match(factory.recordMembers.toString)
- || context.getReference().match(factory.recordMembers.hashCode)
- || context.getReference().match(factory.recordMembers.equals))) {
- requiresRecordClass(eventConsumer);
- CfInstruction constant =
- context.getReference().match(factory.recordMembers.toString)
- ? new CfConstNull()
- : new CfConstNumber(0, ValueType.INT);
- return ImmutableList.of(new CfStackInstruction(CfStackInstruction.Opcode.Pop), constant);
- }
-
- CfInstruction desugaredInstruction = desugarInstruction(instruction, context);
- return desugaredInstruction == null ? null : Collections.singletonList(desugaredInstruction);
- }
-
- private CfInstruction desugarInstruction(CfInstruction instruction, ProgramMethod context) {
assert !instruction.isInitClass();
- // TODO(b/179146128): Rewrite record invoke-dynamic here.
+ if (instruction.isInvokeDynamic() && needsDesugaring(instruction.asInvokeDynamic(), context)) {
+ return desugarInvokeDynamicOnRecord(
+ instruction.asInvokeDynamic(), context, eventConsumer, methodProcessingContext);
+ }
if (instruction.isInvoke()) {
CfInvoke cfInvoke = instruction.asInvoke();
DexMethod newMethod =
rewriteMethod(cfInvoke.getMethod(), cfInvoke.isInvokeSuper(context.getHolderType()));
if (newMethod != cfInvoke.getMethod()) {
- return new CfInvoke(cfInvoke.getOpcode(), newMethod, cfInvoke.isInterface());
+ return Collections.singletonList(
+ new CfInvoke(cfInvoke.getOpcode(), newMethod, cfInvoke.isInterface()));
}
}
return null;
}
+ public List<CfInstruction> desugarInvokeDynamicOnRecord(
+ CfInvokeDynamic invokeDynamic,
+ ProgramMethod context,
+ CfInstructionDesugaringEventConsumer eventConsumer,
+ MethodProcessingContext methodProcessingContext) {
+ assert needsDesugaring(invokeDynamic, context);
+ DexCallSite callSite = invokeDynamic.getCallSite();
+ DexValueType recordValueType = callSite.bootstrapArgs.get(0).asDexValueType();
+ DexValueString valueString = callSite.bootstrapArgs.get(1).asDexValueString();
+ DexString fieldNames = valueString.getValue();
+ DexField[] fields = new DexField[callSite.bootstrapArgs.size() - 2];
+ for (int i = 2; i < callSite.bootstrapArgs.size(); i++) {
+ DexValueMethodHandle handle = callSite.bootstrapArgs.get(i).asDexValueMethodHandle();
+ fields[i - 2] = handle.value.member.asDexField();
+ }
+ DexProgramClass recordClass =
+ appView.definitionFor(recordValueType.getValue()).asProgramClass();
+ if (callSite.methodName == factory.toStringMethodName) {
+ DexString simpleName =
+ ClassNameComputationInfo.ClassNameMapping.SIMPLE_NAME.map(
+ recordValueType.getValue().toDescriptorString(), context.getHolder(), factory);
+ return desugarInvokeRecordToString(
+ recordClass, fieldNames, fields, simpleName, eventConsumer, methodProcessingContext);
+ }
+ if (callSite.methodName == factory.hashCodeMethodName) {
+ return desugarInvokeRecordHashCode(
+ recordClass, fields, eventConsumer, methodProcessingContext);
+ }
+ if (callSite.methodName == factory.equalsMethodName) {
+ return desugarInvokeRecordEquals(recordClass, fields, eventConsumer, methodProcessingContext);
+ }
+ throw new Unreachable("Invoke dynamic needs record desugaring but could not be desugared.");
+ }
+
+ private ProgramMethod synthesizeGetFieldsAsObjectsMethod(
+ DexProgramClass clazz, DexField[] fields, DexMethod method) {
+ MethodAccessFlags methodAccessFlags =
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC, false);
+ DexEncodedMethod encodedMethod =
+ new DexEncodedMethod(
+ method,
+ methodAccessFlags,
+ MethodTypeSignature.noSignature(),
+ DexAnnotationSet.empty(),
+ ParameterAnnotationsList.empty(),
+ null,
+ true);
+ encodedMethod.setCode(
+ new RecordGetFieldsAsObjectsCfCodeProvider(appView, factory.recordTagType, fields)
+ .generateCfCode(),
+ appView);
+ return new ProgramMethod(clazz, encodedMethod);
+ }
+
+ private void ensureGetFieldsAsObjects(
+ DexProgramClass clazz, DexField[] fields, RecordDesugaringEventConsumer eventConsumer) {
+ DexMethod method = getFieldsAsObjectsMethod(clazz.type);
+ synchronized (clazz.getMethodCollection()) {
+ ProgramMethod getFieldsAsObjects = clazz.lookupProgramMethod(method);
+ if (getFieldsAsObjects == null) {
+ getFieldsAsObjects = synthesizeGetFieldsAsObjectsMethod(clazz, fields, method);
+ clazz.addVirtualMethod(getFieldsAsObjects.getDefinition());
+ if (eventConsumer != null) {
+ eventConsumer.acceptRecordMethod(getFieldsAsObjects);
+ }
+ }
+ }
+ }
+
+ private DexMethod getFieldsAsObjectsMethod(DexType holder) {
+ return factory.createMethod(
+ holder, factory.createProto(factory.objectArrayType), GET_FIELDS_AS_OBJECTS_METHOD_NAME);
+ }
+
+ private ProgramMethod synthesizeRecordHelper(
+ DexProto helperProto,
+ BiFunction<InternalOptions, DexMethod, CfCode> codeGenerator,
+ MethodProcessingContext methodProcessingContext) {
+ return appView
+ .getSyntheticItems()
+ .createMethod(
+ SyntheticNaming.SyntheticKind.RECORD_HELPER,
+ methodProcessingContext.createUniqueContext(),
+ factory,
+ builder ->
+ builder
+ .setProto(helperProto)
+ .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
+ .setCode(methodSig -> codeGenerator.apply(appView.options(), methodSig)));
+ }
+
+ private List<CfInstruction> desugarInvokeRecordHashCode(
+ DexProgramClass recordClass,
+ DexField[] fields,
+ CfInstructionDesugaringEventConsumer eventConsumer,
+ MethodProcessingContext methodProcessingContext) {
+ ensureGetFieldsAsObjects(recordClass, fields, eventConsumer);
+ ProgramMethod programMethod =
+ synthesizeRecordHelper(
+ recordHashCodeHelperProto,
+ RecordCfMethods::RecordMethods_hashCode,
+ methodProcessingContext);
+ eventConsumer.acceptRecordMethod(programMethod);
+ return ImmutableList.of(
+ new CfInvoke(Opcodes.INVOKESTATIC, programMethod.getReference(), false));
+ }
+
+ private List<CfInstruction> desugarInvokeRecordEquals(
+ DexProgramClass recordClass,
+ DexField[] fields,
+ CfInstructionDesugaringEventConsumer eventConsumer,
+ MethodProcessingContext methodProcessingContext) {
+ ensureGetFieldsAsObjects(recordClass, fields, eventConsumer);
+ ProgramMethod programMethod =
+ synthesizeRecordHelper(
+ recordEqualsHelperProto,
+ RecordCfMethods::RecordMethods_equals,
+ methodProcessingContext);
+ eventConsumer.acceptRecordMethod(programMethod);
+ return ImmutableList.of(
+ new CfInvoke(Opcodes.INVOKESTATIC, programMethod.getReference(), false));
+ }
+
+ private List<CfInstruction> desugarInvokeRecordToString(
+ DexProgramClass recordClass,
+ DexString fieldNames,
+ DexField[] fields,
+ DexString simpleName,
+ CfInstructionDesugaringEventConsumer eventConsumer,
+ MethodProcessingContext methodProcessingContext) {
+ ensureGetFieldsAsObjects(recordClass, fields, eventConsumer);
+ ArrayList<CfInstruction> instructions = new ArrayList<>();
+ instructions.add(new CfConstString(simpleName));
+ instructions.add(new CfConstString(fieldNames));
+ ProgramMethod programMethod =
+ synthesizeRecordHelper(
+ recordToStringHelperProto,
+ RecordCfMethods::RecordMethods_toString,
+ methodProcessingContext);
+ eventConsumer.acceptRecordMethod(programMethod);
+ instructions.add(new CfInvoke(Opcodes.INVOKESTATIC, programMethod.getReference(), false));
+ return instructions;
+ }
+
@Override
public boolean needsDesugaring(CfInstruction instruction, ProgramMethod context) {
assert !instruction.isInitClass();
@@ -161,7 +316,6 @@
@Override
public boolean needsDesugaring(DexProgramClass clazz) {
- assert clazz.isRecord() || clazz.superType != factory.recordType;
return clazz.isRecord();
}
@@ -210,14 +364,85 @@
return rewriteMethod(method, isSuper) != method;
}
+ private boolean needsDesugaring(CfInvokeDynamic invokeDynamic, ProgramMethod context) {
+ DexCallSite callSite = invokeDynamic.getCallSite();
+ // 1. Validates this is an invoke-static to ObjectMethods#bootstrap.
+ DexMethodHandle bootstrapMethod = callSite.bootstrapMethod;
+ if (!bootstrapMethod.type.isInvokeStatic()) {
+ return false;
+ }
+ if (bootstrapMethod.member != factory.objectMethodsMembers.bootstrap) {
+ return false;
+ }
+ // From there on we assume in the assertions that the invoke to the library method is
+ // well-formed. If the invoke is not well formed assertions will fail but the execution is
+ // correct.
+ if (bootstrapMethod.isInterface) {
+ assert false
+ : "Invoke-dynamic invoking non interface method ObjectMethods#bootstrap as an interface"
+ + " method.";
+ return false;
+ }
+ // 2. Validate the bootstrapArgs include the record type, the instance field names and
+ // the corresponding instance getters.
+ if (callSite.bootstrapArgs.size() < 2) {
+ assert false
+ : "Invoke-dynamic invoking method ObjectMethods#bootstrap with less than 2 parameters.";
+ return false;
+ }
+ DexValueType recordType = callSite.bootstrapArgs.get(0).asDexValueType();
+ if (recordType == null) {
+ assert false : "Invoke-dynamic invoking method ObjectMethods#bootstrap with an invalid type.";
+ return false;
+ }
+ DexClass recordClass = appView.definitionFor(recordType.getValue());
+ if (recordClass == null || recordClass.isNotProgramClass()) {
+ return false;
+ }
+ DexValueString valueString = callSite.bootstrapArgs.get(1).asDexValueString();
+ if (valueString == null) {
+ assert false
+ : "Invoke-dynamic invoking method ObjectMethods#bootstrap with invalid field names.";
+ return false;
+ }
+ DexString fieldNames = valueString.getValue();
+ assert fieldNames.toString().isEmpty()
+ || (fieldNames.toString().split(";").length == callSite.bootstrapArgs.size() - 2);
+ assert recordClass.instanceFields().size() == callSite.bootstrapArgs.size() - 2;
+ for (int i = 2; i < callSite.bootstrapArgs.size(); i++) {
+ DexValueMethodHandle handle = callSite.bootstrapArgs.get(i).asDexValueMethodHandle();
+ if (handle == null
+ || !handle.value.type.isInstanceGet()
+ || !handle.value.member.isDexField()) {
+ assert false
+ : "Invoke-dynamic invoking method ObjectMethods#bootstrap with invalid getters.";
+ return false;
+ }
+ }
+ // 3. Create the invoke-record instruction.
+ if (callSite.methodName == factory.toStringMethodName) {
+ assert callSite.methodProto == factory.createProto(factory.stringType, recordClass.getType());
+ return true;
+ }
+ if (callSite.methodName == factory.hashCodeMethodName) {
+ assert callSite.methodProto == factory.createProto(factory.intType, recordClass.getType());
+ return true;
+ }
+ if (callSite.methodName == factory.equalsMethodName) {
+ assert callSite.methodProto
+ == factory.createProto(factory.booleanType, recordClass.getType(), factory.objectType);
+ return true;
+ }
+ return false;
+ }
+
@SuppressWarnings("ConstantConditions")
private DexMethod rewriteMethod(DexMethod method, boolean isSuper) {
- if (method.holder != factory.recordType || method.isInstanceInitializer(factory)) {
+ if (!(method == factory.recordMembers.equals
+ || method == factory.recordMembers.hashCode
+ || method == factory.recordMembers.toString)) {
return method;
}
- assert method == factory.recordMembers.equals
- || method == factory.recordMembers.hashCode
- || method == factory.recordMembers.toString;
if (isSuper) {
// TODO(b/179146128): Support rewriting invoke-super to a Record method.
throw new CompilationError("Rewrite invoke-super to abstract method error.");
@@ -234,22 +459,61 @@
private DexProgramClass synthesizeR8Record() {
DexItemFactory factory = appView.dexItemFactory();
+ DexClass r8RecordClass =
+ appView.appInfo().definitionForWithoutExistenceAssert(factory.recordTagType);
+ if (r8RecordClass != null && r8RecordClass.isProgramClass()) {
+ appView
+ .options()
+ .reporter
+ .error(
+ "D8/R8 is compiling a mix of desugared and non desugared input using"
+ + " java.lang.Record, but the application reader did not import correctly "
+ + factory.recordTagType.toString());
+ }
DexClass recordClass =
appView.appInfo().definitionForWithoutExistenceAssert(factory.recordType);
if (recordClass != null && recordClass.isProgramClass()) {
return null;
}
- assert recordClass == null || recordClass.isLibraryClass();
+ return synchronizedSynthesizeR8Record();
+ }
+
+ private synchronized DexProgramClass synchronizedSynthesizeR8Record() {
+ DexItemFactory factory = appView.dexItemFactory();
+ DexClass recordClass =
+ appView.appInfo().definitionForWithoutExistenceAssert(factory.recordType);
+ if (recordClass != null && recordClass.isProgramClass()) {
+ return null;
+ }
DexEncodedMethod init = synthesizeRecordInitMethod();
- // TODO(b/179146128): We may want to remove here the class from the library classes if present
- // in cf to cf.
+ DexEncodedMethod abstractGetFieldsAsObjectsMethod =
+ synthesizeAbstractGetFieldsAsObjectsMethod();
return appView
.getSyntheticItems()
.createFixedClassFromType(
SyntheticNaming.SyntheticKind.RECORD_TAG,
factory.recordType,
factory,
- builder -> builder.setAbstract().setDirectMethods(Collections.singletonList(init)));
+ builder ->
+ builder
+ .setAbstract()
+ .setVirtualMethods(ImmutableList.of(abstractGetFieldsAsObjectsMethod))
+ .setDirectMethods(ImmutableList.of(init)));
+ }
+
+ private DexEncodedMethod synthesizeAbstractGetFieldsAsObjectsMethod() {
+ MethodAccessFlags methodAccessFlags =
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT, false);
+ DexMethod fieldsAsObjectsMethod = getFieldsAsObjectsMethod(factory.recordType);
+ return new DexEncodedMethod(
+ fieldsAsObjectsMethod,
+ methodAccessFlags,
+ MethodTypeSignature.noSignature(),
+ DexAnnotationSet.empty(),
+ ParameterAnnotationsList.empty(),
+ null,
+ true);
}
private DexEncodedMethod synthesizeRecordInitMethod() {
@@ -266,7 +530,7 @@
null,
true);
init.setCode(
- new CallObjectInitCfCodeProvider(appView, factory.r8RecordType).generateCfCode(), appView);
+ new CallObjectInitCfCodeProvider(appView, factory.recordTagType).generateCfCode(), appView);
return init;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index b7b0db0..3f7a705 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -2162,6 +2162,113 @@
ImmutableList.of());
}
+ public static CfCode IntegerMethods_parseIntSubsequenceWithRadixDalvik(
+ InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ CfLabel label4 = new CfLabel();
+ CfLabel label5 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 3,
+ 4,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.INT, 2),
+ new CfLoad(ValueType.INT, 1),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+ new CfConstNumber(2, ValueType.INT),
+ new CfIfCmp(If.Type.LT, ValueType.INT, label4),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.INT, 1),
+ label1,
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(
+ options.itemFactory.charType, options.itemFactory.intType),
+ options.itemFactory.createString("charAt")),
+ true),
+ new CfConstNumber(43, ValueType.INT),
+ new CfIfCmp(If.Type.NE, ValueType.INT, label4),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.INT, 1),
+ new CfConstNumber(1, ValueType.INT),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+ label2,
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(
+ options.itemFactory.charType, options.itemFactory.intType),
+ options.itemFactory.createString("charAt")),
+ true),
+ new CfLoad(ValueType.INT, 3),
+ new CfInvoke(
+ 184,
+ options.itemFactory.createMethod(
+ options.itemFactory.boxedCharType,
+ options.itemFactory.createProto(
+ options.itemFactory.intType,
+ options.itemFactory.charType,
+ options.itemFactory.intType),
+ options.itemFactory.createString("digit")),
+ false),
+ new CfIf(If.Type.LT, ValueType.INT, label4),
+ label3,
+ new CfIinc(1, 1),
+ label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.INT, 1),
+ new CfLoad(ValueType.INT, 2),
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
+ options.itemFactory.createString("subSequence")),
+ true),
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
+ options.itemFactory.createString("toString")),
+ true),
+ new CfLoad(ValueType.INT, 3),
+ new CfInvoke(
+ 184,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/Integer;"),
+ options.itemFactory.createProto(
+ options.itemFactory.intType,
+ options.itemFactory.stringType,
+ options.itemFactory.intType),
+ options.itemFactory.createString("parseInt")),
+ false),
+ new CfReturn(ValueType.INT),
+ label5),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
public static CfCode IntegerMethods_parseUnsignedInt(InternalOptions options, DexMethod method) {
CfLabel label0 = new CfLabel();
CfLabel label1 = new CfLabel();
@@ -2737,6 +2844,113 @@
ImmutableList.of());
}
+ public static CfCode LongMethods_parseLongSubsequenceWithRadixDalvik(
+ InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ CfLabel label4 = new CfLabel();
+ CfLabel label5 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 3,
+ 4,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.INT, 2),
+ new CfLoad(ValueType.INT, 1),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+ new CfConstNumber(2, ValueType.INT),
+ new CfIfCmp(If.Type.LT, ValueType.INT, label4),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.INT, 1),
+ label1,
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(
+ options.itemFactory.charType, options.itemFactory.intType),
+ options.itemFactory.createString("charAt")),
+ true),
+ new CfConstNumber(43, ValueType.INT),
+ new CfIfCmp(If.Type.NE, ValueType.INT, label4),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.INT, 1),
+ new CfConstNumber(1, ValueType.INT),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
+ label2,
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(
+ options.itemFactory.charType, options.itemFactory.intType),
+ options.itemFactory.createString("charAt")),
+ true),
+ new CfLoad(ValueType.INT, 3),
+ new CfInvoke(
+ 184,
+ options.itemFactory.createMethod(
+ options.itemFactory.boxedCharType,
+ options.itemFactory.createProto(
+ options.itemFactory.intType,
+ options.itemFactory.charType,
+ options.itemFactory.intType),
+ options.itemFactory.createString("digit")),
+ false),
+ new CfIf(If.Type.LT, ValueType.INT, label4),
+ label3,
+ new CfIinc(1, 1),
+ label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.INT, 1),
+ new CfLoad(ValueType.INT, 2),
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
+ options.itemFactory.createString("subSequence")),
+ true),
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
+ options.itemFactory.createString("toString")),
+ true),
+ new CfLoad(ValueType.INT, 3),
+ new CfInvoke(
+ 184,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createProto(
+ options.itemFactory.longType,
+ options.itemFactory.stringType,
+ options.itemFactory.intType),
+ options.itemFactory.createString("parseLong")),
+ false),
+ new CfReturn(ValueType.LONG),
+ label5),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
public static CfCode LongMethods_parseUnsignedLong(InternalOptions options, DexMethod method) {
CfLabel label0 = new CfLabel();
CfLabel label1 = new CfLabel();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java b/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java
index 28bbf14..8f9421d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java
@@ -13,10 +13,10 @@
// Returns true if this method is pinned from the perspective of optimizations that attempt to
// remove method arguments.
public static boolean isPinned(DexEncodedMethod method, AppView<AppInfoWithLiveness> appView) {
- return appView.appInfo().isPinned(method.method)
- || appView.appInfo().isBootstrapMethod(method.method)
- || appView.appInfo().isFailedResolutionTarget(method.method)
- || appView.appInfo().isMethodTargetedByInvokeDynamic(method.method)
+ return appView.appInfo().isPinned(method.getReference())
+ || appView.appInfo().isBootstrapMethod(method.getReference())
+ || appView.appInfo().isFailedResolutionTarget(method.getReference())
+ || appView.appInfo().isMethodTargetedByInvokeDynamic(method.getReference())
|| method.accessFlags.isNative();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
index 5eb23bb..43be45b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
@@ -384,12 +384,13 @@
}
}
}
- assert argumentsSeen == code.method().method.getArity() + (code.method().isStatic() ? 0 : 1)
+ assert argumentsSeen
+ == code.method().getReference().getArity() + (code.method().isStatic() ? 0 : 1)
: "args: "
+ argumentsSeen
+ " != "
+ "arity: "
- + code.method().method.getArity()
+ + code.method().getReference().getArity()
+ ", static: "
+ code.method().isStatic();
// After packed Argument instructions, add Assume and constant instructions.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index b176db1..3551295 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -164,7 +164,7 @@
// Set initial values for static fields from the definitive static put instructions collected.
finalFieldPuts.forEach(
(field, put) -> {
- DexType fieldType = field.field.type;
+ DexType fieldType = field.getReference().type;
Value value = put.value().getAliasedValue();
if (unnecessaryStaticPuts.contains(put)) {
if (fieldType == dexItemFactory.stringType) {
@@ -253,7 +253,7 @@
.map(appInfoWithLiveness::resolveField)
.map(FieldResolutionResult::getResolvedField)
.filter(appInfoWithLiveness::isStaticFieldWrittenOnlyInEnclosingStaticInitializer)
- .map(field -> field.field)
+ .map(field -> field.getReference())
.collect(Collectors.toSet());
// Then retain only these fields that are actually no longer being written to.
@@ -264,7 +264,7 @@
DexEncodedField encodedField =
appInfoWithLiveness.resolveField(field).getResolvedField();
if (encodedField != null) {
- candidates.remove(encodedField.field);
+ candidates.remove(encodedField.getReference());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index d3dc297..32ec969 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -263,7 +263,7 @@
if (appView
.dexItemFactory()
.objectsMethods
- .isRequireNonNullMethod(code.method().method)) {
+ .isRequireNonNullMethod(code.method().getReference())) {
continue;
}
@@ -524,7 +524,8 @@
int selfRecursionFanOut = 0;
Instruction lastSelfRecursiveCall = null;
for (Instruction i : code.instructions()) {
- if (i.isInvokeMethod() && i.asInvokeMethod().getInvokedMethod() == code.method().method) {
+ if (i.isInvokeMethod()
+ && i.asInvokeMethod().getInvokedMethod() == code.method().getReference()) {
selfRecursionFanOut++;
lastSelfRecursiveCall = i;
}
@@ -3720,7 +3721,7 @@
InstructionListIterator iterator = block.listIterator(code);
// Attach some synthetic position to all inserted code.
- Position position = Position.synthetic(1, method.method, null);
+ Position position = Position.synthetic(1, method.getReference(), null);
iterator.setInsertionPosition(position);
// Split arguments into their own block.
@@ -3748,7 +3749,7 @@
Value value = addConstString(code, iterator, "INVOKE ");
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
- value = addConstString(code, iterator, method.method.qualifiedName());
+ value = addConstString(code, iterator, method.getReference().qualifiedName());
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
Value openParenthesis = addConstString(code, iterator, "(");
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index fa3886e..0cc7497 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -387,7 +387,7 @@
}
// Change the invoke-virtual instruction to target the refined resolution result instead.
- return newResolutionResult.getResolvedMethod().method;
+ return newResolutionResult.getResolvedMethod().getReference();
}
private boolean isRebindingNewClassIntoMainDex(ProgramMethod context, DexMethod reboundMethod) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
index 20e0515..9b738b6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
@@ -30,7 +30,7 @@
* <p>If the method has no normal exits, then null is returned.
*/
public TypeElement computeDynamicReturnType(DexEncodedMethod method, IRCode code) {
- assert method.method.proto.returnType.isReferenceType();
+ assert method.getReference().proto.returnType.isReferenceType();
List<TypeElement> returnedTypes = new ArrayList<>();
for (BasicBlock block : code.blocks) {
JumpInstruction exitInstruction = block.exit();
@@ -43,7 +43,7 @@
}
public ClassTypeElement computeDynamicLowerBoundType(DexEncodedMethod method, IRCode code) {
- assert method.method.proto.returnType.isReferenceType();
+ assert method.getReference().proto.returnType.isReferenceType();
ClassTypeElement result = null;
for (BasicBlock block : code.blocks) {
JumpInstruction exitInstruction = block.exit();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index 976e869..e00c267 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -370,6 +370,17 @@
// This will fail at runtime.
return ConstraintWithTarget.NEVER;
}
+ if (!appView
+ .appInfo()
+ .getClassToFeatureSplitMap()
+ .isInBaseOrSameFeatureAs(
+ resolvedMember.getHolderType(),
+ context.asProgramMethod(),
+ appView.getSyntheticItems())) {
+ // We never inline into the base from a feature (calls should never happen) and we
+ // never inline between features, so this check should be sufficient.
+ return ConstraintWithTarget.NEVER;
+ }
DexType resolvedHolder = graphLens.lookupType(resolvedMember.getHolderType());
assert initialResolutionHolder != null;
ConstraintWithTarget memberConstraintWithTarget =
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberPoolCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberPoolCollection.java
index 4f699e6..bd0376b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberPoolCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberPoolCollection.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.WorkList;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
import java.util.ArrayDeque;
@@ -26,6 +27,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
+import java.util.function.BiFunction;
import java.util.function.Predicate;
// Per-class collection of member signatures.
@@ -158,14 +160,16 @@
public static class MemberPool<T> {
- private Equivalence<T> equivalence;
+ private final DexClass clazz;
+ private final Equivalence<T> equivalence;
private MemberPool<T> superType;
private final Set<MemberPool<T>> interfaces = new HashSet<>();
private final Set<MemberPool<T>> subTypes = new HashSet<>();
private final Set<Wrapper<T>> memberPool = new HashSet<>();
- MemberPool(Equivalence<T> equivalence) {
+ MemberPool(Equivalence<T> equivalence, DexClass clazz) {
this.equivalence = equivalence;
+ this.clazz = clazz;
}
synchronized void linkSupertype(MemberPool<T> superType) {
@@ -193,36 +197,74 @@
}
public boolean hasSeen(Wrapper<T> member) {
- return hasSeenAbove(member, true) || hasSeenStrictlyBelow(member);
+ return fold(member, false, true, (t, ignored) -> true);
}
public boolean hasSeenDirectly(Wrapper<T> member) {
- return memberPool.contains(member);
+ return here(member, false, (t, ignored) -> true);
}
public boolean hasSeenStrictlyAbove(Wrapper<T> member) {
- return hasSeenAbove(member, false);
- }
-
- private boolean hasSeenAbove(Wrapper<T> member, boolean inclusive) {
- if (inclusive && hasSeenDirectly(member)) {
- return true;
- }
- return (superType != null && superType.hasSeenAbove(member, true))
- || interfaces.stream().anyMatch(itf -> itf.hasSeenAbove(member, true));
+ return above(member, false, false, true, (t, ignored) -> true);
}
public boolean hasSeenStrictlyBelow(Wrapper<T> member) {
- return hasSeenBelow(member, false);
+ return below(member, false, true, (t, ignored) -> true);
}
- private boolean hasSeenBelow(Wrapper<T> member, boolean inclusive) {
- if (inclusive
- && (hasSeenDirectly(member)
- || interfaces.stream().anyMatch(itf -> itf.hasSeenAbove(member, true)))) {
- return true;
+ private <S> S above(
+ Wrapper<T> member,
+ boolean inclusive,
+ S value,
+ S terminator,
+ BiFunction<DexClass, S, S> accumulator) {
+ WorkList<MemberPool<T>> workList = WorkList.newIdentityWorkList(this);
+ while (workList.hasNext()) {
+ MemberPool<T> next = workList.next();
+ if (inclusive) {
+ value = next.here(member, value, accumulator);
+ if (value == terminator) {
+ return value;
+ }
+ }
+ inclusive = true;
+ if (next.superType != null) {
+ workList.addIfNotSeen(next.superType);
+ }
+ workList.addIfNotSeen(next.interfaces);
}
- return subTypes.stream().anyMatch(subType -> subType.hasSeenBelow(member, true));
+ return value;
+ }
+
+ private <S> S here(Wrapper<T> member, S value, BiFunction<DexClass, S, S> accumulator) {
+ if (memberPool.contains(member)) {
+ return accumulator.apply(clazz, value);
+ }
+ return value;
+ }
+
+ public <S> S below(
+ Wrapper<T> member, S value, S terminator, BiFunction<DexClass, S, S> accumulator) {
+ WorkList<MemberPool<T>> workList = WorkList.newIdentityWorkList(this.subTypes);
+ while (workList.hasNext()) {
+ MemberPool<T> next = workList.next();
+ value = next.here(member, value, accumulator);
+ if (value == terminator) {
+ return value;
+ }
+ workList.addIfNotSeen(next.interfaces);
+ workList.addIfNotSeen(next.subTypes);
+ }
+ return value;
+ }
+
+ public <S> S fold(
+ Wrapper<T> member, S initialValue, S terminator, BiFunction<DexClass, S, S> accumulator) {
+ S value = above(member, true, initialValue, terminator, accumulator);
+ if (value == terminator) {
+ return value;
+ }
+ return below(member, initialValue, terminator, accumulator);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java
index 593e827..652c185 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MethodPoolCollection.java
@@ -54,18 +54,19 @@
Runnable computeMemberPoolForClass(DexClass clazz) {
return () -> {
MemberPool<DexMethod> methodPool =
- memberPools.computeIfAbsent(clazz, k -> new MemberPool<>(equivalence));
+ memberPools.computeIfAbsent(clazz, k -> new MemberPool<>(equivalence, k));
clazz.forEachMethod(
encodedMethod -> {
if (methodTester.test(encodedMethod)) {
- methodPool.seen(equivalence.wrap(encodedMethod.method));
+ methodPool.seen(equivalence.wrap(encodedMethod.getReference()));
}
});
if (clazz.superType != null) {
DexClass superClazz = appView.definitionFor(clazz.superType);
if (superClazz != null) {
MemberPool<DexMethod> superPool =
- memberPools.computeIfAbsent(superClazz, k -> new MemberPool<>(equivalence));
+ memberPools.computeIfAbsent(
+ superClazz, k -> new MemberPool<>(equivalence, superClazz));
superPool.linkSubtype(methodPool);
methodPool.linkSupertype(superPool);
}
@@ -75,7 +76,7 @@
DexClass subClazz = appView.definitionFor(subtype);
if (subClazz != null) {
MemberPool<DexMethod> childPool =
- memberPools.computeIfAbsent(subClazz, k -> new MemberPool<>(equivalence));
+ memberPools.computeIfAbsent(subClazz, k -> new MemberPool<>(equivalence, subClazz));
methodPool.linkSubtype(childPool);
childPool.linkInterface(methodPool);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index f802efe..014337c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -363,14 +363,14 @@
fieldInitializationInfos.forEachWithDeterministicOrder(
appView,
(field, info) -> {
- if (!appView.appInfo().withLiveness().mayPropagateValueFor(field.field)) {
+ if (!appView.appInfo().withLiveness().mayPropagateValueFor(field.getReference())) {
return;
}
if (info.isArgumentInitializationInfo()) {
Value value =
invoke.getArgument(info.asArgumentInitializationInfo().getArgumentIndex());
Value object = invoke.getReceiver().getAliasedValue();
- FieldAndObject fieldAndObject = new FieldAndObject(field.field, object);
+ FieldAndObject fieldAndObject = new FieldAndObject(field.getReference(), object);
if (field.isFinal()) {
activeState.putFinalInstanceField(fieldAndObject, new ExistingValue(value));
} else {
@@ -380,7 +380,7 @@
SingleValue value = info.asSingleValue();
if (value.isMaterializableInContext(appView.withLiveness(), method)) {
Value object = invoke.getReceiver().getAliasedValue();
- FieldAndObject fieldAndObject = new FieldAndObject(field.field, object);
+ FieldAndObject fieldAndObject = new FieldAndObject(field.getReference(), object);
if (field.isFinal()) {
activeState.putFinalInstanceField(fieldAndObject, new MaterializableValue(value));
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index 6758593..d532b9b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -178,7 +178,7 @@
});
new Rewriter(code, instructionIterator, serviceLoaderLoad)
- .perform(classLoaderInvoke, synthesizedMethod.method);
+ .perform(classLoaderInvoke, synthesizedMethod.getReference());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
index 7bec65e..5536f0e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
@@ -100,7 +100,7 @@
}
private void extractSwitchMap(DexEncodedField encodedField, IRCode initializer) {
- DexField field = encodedField.field;
+ DexField field = encodedField.getReference();
Int2ReferenceMap<DexField> switchMap = new Int2ReferenceArrayMap<>();
// Find each array-put instruction that updates an entry of the array that is stored in
@@ -162,7 +162,7 @@
private boolean maybeIsSwitchMap(DexEncodedField dexEncodedField) {
// We are looking for synthetic fields of type int[].
- DexField field = dexEncodedField.field;
+ DexField field = dexEncodedField.getReference();
return dexEncodedField.accessFlags.isSynthetic()
&& (field.name.startsWith(switchMapPrefix) || field.name.startsWith(kotlinSwitchMapPrefix))
&& field.type == intArrayType;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index d60ba25..df30aac 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
@@ -28,11 +28,9 @@
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneMap;
-import com.android.tools.r8.utils.collections.EmptyBidirectionalOneToOneMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.BiMap;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.HashMap;
@@ -51,21 +49,13 @@
public static class UninstantiatedTypeOptimizationGraphLens extends NestedGraphLens {
- private final AppView<?> appView;
private final Map<DexMethod, ArgumentInfoCollection> removedArgumentsInfoPerMethod;
UninstantiatedTypeOptimizationGraphLens(
BidirectionalOneToOneMap<DexMethod, DexMethod> methodMap,
Map<DexMethod, ArgumentInfoCollection> removedArgumentsInfoPerMethod,
AppView<?> appView) {
- super(
- ImmutableMap.of(),
- methodMap.getForwardMap(),
- new EmptyBidirectionalOneToOneMap<>(),
- methodMap.getInverseOneToOneMap(),
- appView.graphLens(),
- appView.dexItemFactory());
- this.appView = appView;
+ super(appView, EMPTY_FIELD_MAP, methodMap, EMPTY_TYPE_MAP);
this.removedArgumentsInfoPerMethod = removedArgumentsInfoPerMethod;
}
@@ -78,7 +68,8 @@
return prototypeChanges;
}
if (method.getReturnType().isVoidType() && !previous.getReturnType().isVoidType()) {
- prototypeChanges = prototypeChanges.withConstantReturn(previous.getReturnType(), appView);
+ prototypeChanges =
+ prototypeChanges.withConstantReturn(previous.getReturnType(), dexItemFactory());
}
return prototypeChanges.withRemovedArguments(
removedArgumentsInfoPerMethod.getOrDefault(method, ArgumentInfoCollection.empty()));
@@ -158,7 +149,7 @@
for (DexEncodedMethod virtualMethod : clazz.virtualMethods()) {
RewrittenPrototypeDescription prototypeChanges =
RewrittenPrototypeDescription.createForUninstantiatedTypes(
- virtualMethod.method,
+ virtualMethod.getReference(),
appView,
getRemovedArgumentsInfo(virtualMethod, ALLOW_ARGUMENT_REMOVAL));
if (!prototypeChanges.isEmpty()) {
@@ -186,7 +177,7 @@
Set<Wrapper<DexMethod>> usedSignatures = new HashSet<>();
for (DexEncodedMethod method : clazz.methods()) {
if (!prototypeChangesPerMethod.containsKey(method)) {
- usedSignatures.add(equivalence.wrap(method.method));
+ usedSignatures.add(equivalence.wrap(method.getReference()));
}
}
@@ -195,7 +186,7 @@
.getMethodCollection()
.replaceDirectMethods(
encodedMethod -> {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
RewrittenPrototypeDescription prototypeChanges =
prototypeChangesPerMethod.getOrDefault(
encodedMethod, RewrittenPrototypeDescription.none());
@@ -230,7 +221,7 @@
.getMethodCollection()
.replaceVirtualMethods(
encodedMethod -> {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
RewrittenPrototypeDescription prototypeChanges =
getPrototypeChanges(encodedMethod, DISALLOW_ARGUMENT_REMOVAL);
ArgumentInfoCollection removedArgumentsInfo =
@@ -262,7 +253,7 @@
.getMethodCollection()
.replaceVirtualMethods(
encodedMethod -> {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
RewrittenPrototypeDescription prototypeChanges =
getPrototypeChanges(encodedMethod, DISALLOW_ARGUMENT_REMOVAL);
ArgumentInfoCollection removedArgumentsInfo =
@@ -299,11 +290,11 @@
private RewrittenPrototypeDescription getPrototypeChanges(
DexEncodedMethod encodedMethod, Strategy strategy) {
if (ArgumentRemovalUtils.isPinned(encodedMethod, appView)
- || appView.appInfo().isKeepConstantArgumentsMethod(encodedMethod.method)) {
+ || appView.appInfo().isKeepConstantArgumentsMethod(encodedMethod.getReference())) {
return RewrittenPrototypeDescription.none();
}
return RewrittenPrototypeDescription.createForUninstantiatedTypes(
- encodedMethod.method, appView, getRemovedArgumentsInfo(encodedMethod, strategy));
+ encodedMethod.getReference(), appView, getRemovedArgumentsInfo(encodedMethod, strategy));
}
private ArgumentInfoCollection getRemovedArgumentsInfo(
@@ -313,7 +304,7 @@
}
ArgumentInfoCollection.Builder argInfosBuilder = ArgumentInfoCollection.builder();
- DexProto proto = encodedMethod.method.proto;
+ DexProto proto = encodedMethod.getReference().proto;
int offset = encodedMethod.isStatic() ? 0 : 1;
for (int i = 0; i < proto.parameters.size(); ++i) {
DexType type = proto.parameters.values[i];
@@ -329,7 +320,7 @@
private DexMethod getNewMethodSignature(
DexEncodedMethod encodedMethod, RewrittenPrototypeDescription prototypeChanges) {
DexItemFactory dexItemFactory = appView.dexItemFactory();
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
DexProto newProto = prototypeChanges.rewriteProto(encodedMethod, dexItemFactory);
return dexItemFactory.createMethod(method.holder, newProto, method.name);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
index ec1b904..cc8f5b1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
@@ -7,14 +7,12 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ArgumentUse;
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.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
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.GraphLens.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
@@ -27,10 +25,8 @@
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneMap;
-import com.android.tools.r8.utils.collections.EmptyBidirectionalOneToOneMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Streams;
import java.util.BitSet;
import java.util.HashSet;
@@ -57,18 +53,10 @@
private final Map<DexMethod, ArgumentInfoCollection> removedArguments;
UnusedArgumentsGraphLens(
- Map<DexMethod, DexMethod> methodMap,
- BidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures,
- GraphLens previousLens,
- DexItemFactory dexItemFactory,
+ AppView<?> appView,
+ BidirectionalOneToOneMap<DexMethod, DexMethod> methodMap,
Map<DexMethod, ArgumentInfoCollection> removedArguments) {
- super(
- ImmutableMap.of(),
- methodMap,
- new EmptyBidirectionalOneToOneMap<>(),
- originalMethodSignatures,
- previousLens,
- dexItemFactory);
+ super(appView, EMPTY_FIELD_MAP, methodMap, EMPTY_TYPE_MAP);
this.removedArguments = removedArguments;
}
@@ -103,12 +91,7 @@
appView.appInfo().classesWithDeterministicOrder().forEach(this::processVirtualMethods);
if (!methodMapping.isEmpty()) {
- return new UnusedArgumentsGraphLens(
- methodMapping.getForwardMap(),
- methodMapping.getInverseOneToOneMap(),
- appView.graphLens(),
- appView.dexItemFactory(),
- removedArguments);
+ return new UnusedArgumentsGraphLens(appView, methodMapping, removedArguments);
}
return null;
@@ -133,8 +116,8 @@
DexString newName = null;
do {
if (newName == null) {
- newName = method.method.name;
- } else if (!appView.dexItemFactory().isConstructor(method.method)) {
+ newName = method.getReference().name;
+ } else if (!appView.dexItemFactory().isConstructor(method.getReference())) {
newName =
appView
.dexItemFactory()
@@ -142,7 +125,7 @@
SymbolGenerationUtils.numberToIdentifier(
count,
MixedCasing.USE_MIXED_CASE,
- method.method.name.toSourceString().toCharArray()));
+ method.getReference().name.toSourceString().toCharArray()));
} else {
// Constructors must be named `<init>`.
return null;
@@ -156,7 +139,7 @@
DexEncodedMethod removeArguments(
DexEncodedMethod method, DexMethod newSignature, ArgumentInfoCollection unused) {
- boolean removed = usedSignatures.remove(equivalence.wrap(method.method));
+ boolean removed = usedSignatures.remove(equivalence.wrap(method.getReference()));
assert removed;
markSignatureAsUsed(newSignature);
@@ -180,10 +163,12 @@
DexString newName = null;
do {
if (newName == null) {
- newName = method.method.name;
- } else if (!appView.dexItemFactory().isConstructor(method.method)) {
+ newName = method.getReference().name;
+ } else if (!appView.dexItemFactory().isConstructor(method.getReference())) {
newName =
- appView.dexItemFactory().createString(method.method.name.toSourceString() + count);
+ appView
+ .dexItemFactory()
+ .createString(method.getReference().name.toSourceString() + count);
} else {
// Constructors must be named `<init>`.
return null;
@@ -210,7 +195,7 @@
private void processDirectMethods(DexProgramClass clazz) {
UsedSignatures signatures = new UsedSignatures();
for (DexEncodedMethod method : clazz.methods()) {
- signatures.markSignatureAsUsed(method.method);
+ signatures.markSignatureAsUsed(method.getReference());
}
clazz
@@ -220,7 +205,7 @@
// If this is a method with known resolution issues, then don't remove any unused
// arguments.
- if (appView.appInfo().isFailedResolutionTarget(method.method)) {
+ if (appView.appInfo().isFailedResolutionTarget(method.getReference())) {
return method;
}
@@ -229,14 +214,14 @@
DexProto newProto = createProtoWithRemovedArguments(method, unused);
DexMethod newSignature = signatures.getNewSignature(method, newProto);
if (newSignature == null) {
- assert appView.dexItemFactory().isConstructor(method.method);
+ assert appView.dexItemFactory().isConstructor(method.getReference());
return method;
}
DexEncodedMethod newMethod =
signatures.removeArguments(method, newSignature, unused);
synchronized (this) {
- methodMapping.put(method.method, newMethod.method);
- removedArguments.put(newMethod.method, unused);
+ methodMapping.put(method.getReference(), newMethod.getReference());
+ removedArguments.put(newMethod.getReference(), unused);
}
return newMethod;
}
@@ -265,8 +250,8 @@
signatures.removeArguments(
method, signatures.getNewSignature(method, newProto), unused);
- methodMapping.put(method.method, newMethod.method);
- removedArguments.put(newMethod.method, unused);
+ methodMapping.put(method.getReference(), newMethod.getReference());
+ removedArguments.put(newMethod.getReference(), unused);
return newMethod;
}
return method;
@@ -280,7 +265,7 @@
private ArgumentInfoCollection collectUnusedArguments(
DexEncodedMethod method, MemberPool<DexMethod> methodPool) {
if (ArgumentRemovalUtils.isPinned(method, appView)
- || appView.appInfo().isKeepUnusedArgumentsMethod(method.method)) {
+ || appView.appInfo().isKeepUnusedArgumentsMethod(method.getReference())) {
return null;
}
// Only process classfile code objects.
@@ -292,13 +277,13 @@
// an unused argument cannot be removed unless it is unused in all of the related methods in
// the hierarchy.
assert methodPool != null;
- Wrapper<DexMethod> wrapper = equivalence.wrap(method.method);
+ Wrapper<DexMethod> wrapper = equivalence.wrap(method.getReference());
if (methodPool.hasSeenStrictlyAbove(wrapper) || methodPool.hasSeenStrictlyBelow(wrapper)) {
return null;
}
}
int offset = method.accessFlags.isStatic() ? 0 : 1;
- int argumentCount = method.method.proto.parameters.size() + offset;
+ int argumentCount = method.getReference().proto.parameters.size() + offset;
CollectUsedArguments collector = new CollectUsedArguments();
if (!method.accessFlags.isStatic()) {
// TODO(65810338): The receiver cannot be removed without transforming the method to being
@@ -313,7 +298,7 @@
if (!used.get(argumentIndex)) {
RemovedArgumentInfo removedArg =
RemovedArgumentInfo.builder()
- .setType(method.method.proto.parameters.values[argumentIndex - offset])
+ .setType(method.getReference().proto.parameters.values[argumentIndex - offset])
.build();
argInfosBuilder.addArgumentInfo(argumentIndex, removedArg);
}
@@ -326,7 +311,9 @@
private DexProto createProtoWithRemovedArguments(
DexEncodedMethod encodedMethod, ArgumentInfoCollection unused) {
DexType[] parameters = unused.rewriteParameters(encodedMethod);
- return appView.dexItemFactory().createProto(encodedMethod.method.proto.returnType, parameters);
+ return appView
+ .dexItemFactory()
+ .createProto(encodedMethod.getReference().proto.returnType, parameters);
}
private static class CollectUsedArguments extends ArgumentUse {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
index 4857999..f7b79aa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
@@ -290,8 +290,8 @@
// Class must not define finalizer.
DexItemFactory dexItemFactory = appView.dexItemFactory();
for (DexEncodedMethod method : clazz.virtualMethods()) {
- if (method.method.name == dexItemFactory.finalizeMethodName
- && method.method.proto == dexItemFactory.objectMembers.finalize.proto) {
+ if (method.getReference().name == dexItemFactory.finalizeMethodName
+ && method.getReference().proto == dexItemFactory.objectMembers.finalize.proto) {
return EligibilityStatus.NOT_ELIGIBLE;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 27deb32..ce781ec 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -341,7 +341,7 @@
eligibleEnums.add(type);
}
} else if (use.isReturn()) {
- DexType returnType = code.method().method.proto.returnType;
+ DexType returnType = code.method().getReference().proto.returnType;
if (enumUnboxingCandidatesInfo.isCandidate(returnType)) {
eligibleEnums.add(returnType);
}
@@ -500,7 +500,7 @@
for (DexEncodedField staticField : enumClass.staticFields()) {
if (factory.enumMembers.isEnumField(staticField, enumClass.type)) {
ObjectState enumState =
- enumStaticFieldValues.getObjectStateForPossiblyPinnedField(staticField.field);
+ enumStaticFieldValues.getObjectStateForPossiblyPinnedField(staticField.getReference());
if (enumState == null) {
if (staticField.getOptimizationInfo().isDead()) {
// We don't care about unused field data.
@@ -514,11 +514,11 @@
return null;
}
int ordinal = optionalOrdinal.getAsInt();
- unboxedValues.put(staticField.field, ordinalToUnboxedInt(ordinal));
+ unboxedValues.put(staticField.getReference(), ordinalToUnboxedInt(ordinal));
ordinalToObjectState.put(ordinal, enumState);
} else if (factory.enumMembers.isValuesFieldCandidate(staticField, enumClass.type)) {
ObjectState valuesState =
- enumStaticFieldValues.getObjectStateForPossiblyPinnedField(staticField.field);
+ enumStaticFieldValues.getObjectStateForPossiblyPinnedField(staticField.getReference());
if (valuesState == null) {
if (staticField.getOptimizationInfo().isDead()) {
// We don't care about unused field data.
@@ -533,7 +533,7 @@
assert valuesContents == null
|| valuesContents.equals(valuesState.asEnumValuesObjectState());
valuesContents = valuesState.asEnumValuesObjectState();
- valuesField.add(staticField.field);
+ valuesField.add(staticField.getReference());
}
}
@@ -1012,7 +1012,7 @@
return Reason.ELIGIBLE;
}
// The put value has to be of the field type.
- if (field.field.type.toBaseType(factory) != enumClass.type) {
+ if (field.getReference().type.toBaseType(factory) != enumClass.type) {
return Reason.TYPE_MISMATCH_FIELD_PUT;
}
return Reason.ELIGIBLE;
@@ -1095,7 +1095,7 @@
// Return is used for valueOf methods.
if (instruction.isReturn()) {
- DexType returnType = code.method().method.proto.returnType;
+ DexType returnType = code.method().getReference().proto.returnType;
if (returnType != enumClass.type && returnType.toBaseType(factory) != enumClass.type) {
return Reason.IMPLICIT_UP_CAST_IN_RETURN;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
index 88845d9..0d1c0fa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
@@ -85,18 +85,18 @@
}
static boolean isEnumField(DexEncodedField staticField, DexType enumType) {
- return staticField.field.type == enumType
+ return staticField.getReference().type == enumType
&& staticField.accessFlags.isEnum()
&& staticField.accessFlags.isFinal();
}
static boolean matchesValuesField(
DexEncodedField staticField, DexType enumType, DexItemFactory factory) {
- return staticField.field.type.isArrayType()
- && staticField.field.type.toArrayElementType(factory) == enumType
+ return staticField.getReference().type.isArrayType()
+ && staticField.getReference().type.toArrayElementType(factory) == enumType
&& staticField.accessFlags.isSynthetic()
&& staticField.accessFlags.isFinal()
- && staticField.field.name == factory.enumValuesFieldName;
+ && staticField.getReference().name == factory.enumValuesFieldName;
}
private void removeEnumsInAnnotations() {
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 c64e51e..1e27370 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
@@ -4,11 +4,11 @@
package com.android.tools.r8.ir.optimize.enums;
+import com.android.tools.r8.graph.AppView;
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.NestedGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.utils.BooleanUtils;
@@ -16,34 +16,21 @@
import com.android.tools.r8.utils.collections.BidirectionalOneToOneMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import java.util.IdentityHashMap;
import java.util.Map;
-import java.util.Set;
-class EnumUnboxingLens extends GraphLens.NestedGraphLens {
+class EnumUnboxingLens extends NestedGraphLens {
private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod;
- private final Set<DexType> unboxedEnums;
EnumUnboxingLens(
- Map<DexType, DexType> typeMap,
- Map<DexMethod, DexMethod> methodMap,
+ AppView<?> appView,
BidirectionalOneToOneMap<DexField, DexField> fieldMap,
- BidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures,
- GraphLens previousLens,
- DexItemFactory dexItemFactory,
- Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod,
- Set<DexType> unboxedEnums) {
- super(
- typeMap,
- methodMap,
- fieldMap,
- originalMethodSignatures,
- previousLens,
- dexItemFactory);
+ BidirectionalOneToOneMap<DexMethod, DexMethod> methodMap,
+ Map<DexType, DexType> typeMap,
+ Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod) {
+ super(appView, fieldMap, methodMap, typeMap);
this.prototypeChangesPerMethod = prototypeChangesPerMethod;
- this.unboxedEnums = unboxedEnums;
}
@Override
@@ -59,7 +46,7 @@
@Override
protected Invoke.Type mapInvocationType(
DexMethod newMethod, DexMethod originalMethod, Invoke.Type type) {
- if (unboxedEnums.contains(originalMethod.holder)) {
+ if (typeMap.containsKey(originalMethod.getHolderType())) {
// Methods moved from unboxed enums to the utility class are either static or statified.
assert newMethod != originalMethod;
return Invoke.Type.STATIC;
@@ -76,7 +63,7 @@
protected final Map<DexType, DexType> typeMap = new IdentityHashMap<>();
protected final MutableBidirectionalOneToOneMap<DexField, DexField> newFieldSignatures =
new BidirectionalOneToOneHashMap<>();
- protected final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures =
+ protected final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures =
new BidirectionalOneToOneHashMap<>();
private Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod =
@@ -107,7 +94,7 @@
boolean toStatic,
int numberOfExtraNullParameters) {
assert from != to;
- originalMethodSignatures.put(to, from);
+ newMethodSignatures.put(from, to);
int offsetDiff = 0;
int toOffset = BooleanUtils.intValue(!toStatic);
RewrittenPrototypeDescription.ArgumentInfoCollection.Builder builder =
@@ -140,18 +127,14 @@
.withExtraUnusedNullParameters(numberOfExtraNullParameters));
}
- public EnumUnboxingLens build(
- DexItemFactory dexItemFactory, GraphLens previousLens, Set<DexType> unboxedEnums) {
+ public EnumUnboxingLens build(AppView<?> appView) {
assert !typeMap.isEmpty();
return new EnumUnboxingLens(
- typeMap,
- originalMethodSignatures.getInverseOneToOneMap().getForwardMap(),
+ appView,
newFieldSignatures,
- originalMethodSignatures,
- previousLens,
- dexItemFactory,
- ImmutableMap.copyOf(prototypeChangesPerMethod),
- ImmutableSet.copyOf(unboxedEnums));
+ newMethodSignatures,
+ typeMap,
+ ImmutableMap.copyOf(prototypeChangesPerMethod));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index 1602032..4fdd8f6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -21,7 +21,6 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
@@ -72,7 +71,7 @@
private final DexItemFactory factory;
private final EnumDataMap unboxedEnumsData;
private final UnboxedEnumMemberRelocator relocator;
- private NestedGraphLens enumUnboxingLens;
+ private EnumUnboxingLens enumUnboxingLens;
private final Map<DexMethod, DexEncodedMethod> utilityMethods = new ConcurrentHashMap<>();
@@ -128,7 +127,7 @@
ENUM_UNBOXING_UTILITY_METHOD_PREFIX + "zeroCheckMessage");
}
- public void setEnumUnboxingLens(NestedGraphLens enumUnboxingLens) {
+ public void setEnumUnboxingLens(EnumUnboxingLens enumUnboxingLens) {
this.enumUnboxingLens = enumUnboxingLens;
}
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 17d0cc7..8a43d7c 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
@@ -89,7 +89,7 @@
DexProgramClass newHolderClass = appView.definitionFor(newHolderType).asProgramClass();
newHolderClass.addDirectMethods(movedMethods);
});
- return lensBuilder.build(factory, appView.graphLens(), enumsToUnbox);
+ return lensBuilder.build(appView);
}
private void clearEnumToUnboxMethod(DexEncodedMethod enumMethod) {
@@ -103,7 +103,7 @@
private DexEncodedMethod fixupEncodedMethodToUtility(
DexEncodedMethod encodedMethod, DexType newHolder) {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
DexString newMethodName =
factory.createString(
enumUnboxerRewriter.compatibleName(method.holder)
@@ -137,9 +137,10 @@
method.getName().toString() + (method.isNonPrivateVirtualMethod() ? "$enumunboxing$" : "");
DexMethod newMethod = factory.createMethod(method.getHolderType(), newProto, newMethodName);
newMethod = ensureUniqueMethod(method, newMethod);
- int numberOfExtraNullParameters = newMethod.getArity() - method.method.getArity();
+ int numberOfExtraNullParameters = newMethod.getArity() - method.getReference().getArity();
boolean isStatic = method.isStatic();
- lensBuilder.move(method.method, newMethod, isStatic, isStatic, numberOfExtraNullParameters);
+ lensBuilder.move(
+ method.getReference(), newMethod, isStatic, isStatic, numberOfExtraNullParameters);
return method.toTypeSubstitutedMethod(
newMethod,
builder ->
@@ -195,7 +196,7 @@
}
for (int i = 0; i < fields.size(); i++) {
DexEncodedField encodedField = fields.get(i);
- DexField field = encodedField.field;
+ DexField field = encodedField.getReference();
DexType newType = fixupType(field.type);
if (newType != field.type) {
DexField newField = factory.createField(field.holder, newType, field.name);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index 7ad0bdb..70b07a6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -144,7 +144,7 @@
.appInfo()
.resolveMethodOnClass(factory.objectMembers.toString, enumFieldType.getClassType())
.getSingleTarget();
- if (singleTarget != null && singleTarget.method != factory.enumMembers.toString) {
+ if (singleTarget != null && singleTarget.getReference() != factory.enumMembers.toString) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
index ab2b0ac..83fdf6a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
@@ -81,13 +81,13 @@
private TypeElement[] getStaticTypes(AppView<?> appView, DexEncodedMethod method) {
int argOffset = method.isStatic() ? 0 : 1;
- int size = method.method.getArity() + argOffset;
+ int size = method.getReference().getArity() + argOffset;
TypeElement[] staticTypes = new TypeElement[size];
if (!method.isStatic()) {
staticTypes[0] =
TypeElement.fromDexType(method.getHolderType(), definitelyNotNull(), appView);
}
- for (int i = 0; i < method.method.getArity(); i++) {
+ for (int i = 0; i < method.getReference().getArity(); i++) {
staticTypes[i + argOffset] =
TypeElement.fromDexType(method.getParameter(i), maybeNull(), appView);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index aa28923..a48292a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -215,7 +215,7 @@
IRCode code,
OptimizationFeedback feedback,
InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos) {
- assert !appView.appInfo().isPinned(method.method);
+ assert !appView.appInfo().isPinned(method.getReference());
if (!method.isInstanceInitializer()) {
return;
@@ -227,7 +227,7 @@
return;
}
- if (appView.appInfo().mayHaveSideEffects.containsKey(method.method)) {
+ if (appView.appInfo().mayHaveSideEffects.containsKey(method.getReference())) {
return;
}
@@ -813,7 +813,7 @@
DexEncodedMethod method,
IRCode code) {
if (dynamicTypeOptimization != null) {
- DexType staticReturnTypeRaw = method.method.proto.returnType;
+ DexType staticReturnTypeRaw = method.getReference().proto.returnType;
if (!staticReturnTypeRaw.isReferenceType()) {
return;
}
@@ -887,7 +887,7 @@
if (!options.enableSideEffectAnalysis) {
return;
}
- if (appView.appInfo().mayHaveSideEffects.containsKey(method.method)) {
+ if (appView.appInfo().mayHaveSideEffects.containsKey(method.getReference())) {
return;
}
ProgramMethod context = code.context();
@@ -954,8 +954,8 @@
.resolveMethodOnClass(appView.dexItemFactory().objectMembers.finalize, clazz);
DexEncodedMethod target = resolutionResult.getSingleTarget();
return target != null
- && target.method != dexItemFactory.enumMembers.finalize
- && target.method != dexItemFactory.objectMembers.finalize;
+ && target.getReference() != dexItemFactory.enumMembers.finalize
+ && target.getReference() != dexItemFactory.objectMembers.finalize;
}
private void computeReturnValueOnlyDependsOnArguments(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
index df06045..5a12983 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
@@ -108,11 +108,10 @@
public boolean noUpdatesLeft() {
assert appInfoWithLivenessModifier.isEmpty();
assert fieldOptimizationInfos.isEmpty()
- : StringUtils.join(fieldOptimizationInfos.keySet(), ", ");
+ : StringUtils.join(", ", fieldOptimizationInfos.keySet());
assert methodOptimizationInfos.isEmpty()
- : StringUtils.join(methodOptimizationInfos.keySet(), ", ");
- assert processed.isEmpty()
- : StringUtils.join(processed.keySet(), ", ");
+ : StringUtils.join(", ", methodOptimizationInfos.keySet());
+ assert processed.isEmpty() : StringUtils.join(", ", processed.keySet());
return true;
}
@@ -151,9 +150,13 @@
@Override
public void recordFieldHasAbstractValue(
DexEncodedField field, AppView<AppInfoWithLiveness> appView, AbstractValue abstractValue) {
- assert appView.appInfo().getFieldAccessInfoCollection().contains(field.field);
- assert !appView.appInfo().getFieldAccessInfoCollection().get(field.field).hasReflectiveAccess();
- if (appView.appInfo().mayPropagateValueFor(field.field)) {
+ assert appView.appInfo().getFieldAccessInfoCollection().contains(field.getReference());
+ assert !appView
+ .appInfo()
+ .getFieldAccessInfoCollection()
+ .get(field.getReference())
+ .hasReflectiveAccess();
+ if (appView.appInfo().mayPropagateValueFor(field.getReference())) {
getFieldOptimizationInfoForUpdating(field).setAbstractValue(abstractValue);
}
}
@@ -190,7 +193,7 @@
@Override
public synchronized void methodReturnsAbstractValue(
DexEncodedMethod method, AppView<AppInfoWithLiveness> appView, AbstractValue value) {
- if (appView.appInfo().mayPropagateValueFor(method.method)) {
+ if (appView.appInfo().mayPropagateValueFor(method.getReference())) {
getMethodOptimizationInfoForUpdating(method).markReturnsAbstractValue(value);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
index 3fb77d9..5c39d40 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
@@ -66,7 +66,7 @@
@Override
public void recordFieldHasAbstractValue(
DexEncodedField field, AppView<AppInfoWithLiveness> appView, AbstractValue abstractValue) {
- if (appView.appInfo().mayPropagateValueFor(field.field)) {
+ if (appView.appInfo().mayPropagateValueFor(field.getReference())) {
field.getMutableOptimizationInfo().setAbstractValue(abstractValue);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java
index 9fa412a..aca1f76 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java
@@ -47,7 +47,7 @@
public void recordInitializationInfo(
DexEncodedField field, InstanceFieldInitializationInfo info) {
- recordInitializationInfo(field.field, info);
+ recordInitializationInfo(field.getReference(), info);
}
public Builder recordInitializationInfo(DexField field, InstanceFieldInitializationInfo info) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java
index 6fa0363..2081721 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java
@@ -57,7 +57,8 @@
@Override
public InstanceFieldInitializationInfo get(DexEncodedField field) {
- return infos.getOrDefault(field.field, UnknownInstanceFieldInitializationInfo.getInstance());
+ return infos.getOrDefault(
+ field.getReference(), UnknownInstanceFieldInitializationInfo.getInstance());
}
@Override
@@ -85,7 +86,7 @@
List<String> strings = new ArrayList<>();
infos.forEach((field, info) -> strings.add(field.toSourceString() + " -> " + info));
return "NonTrivialInstanceFieldInitializationInfoCollection("
- + StringUtils.join(strings, "; ")
+ + StringUtils.join("; ", strings)
+ ")";
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
index ee2d4b5..257cc15 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
@@ -147,7 +147,7 @@
"not a valid inlining reason (was: "
+ reason
+ ", allowed: one of "
- + StringUtils.join(validInliningReasons, ", ")
+ + StringUtils.join(", ", validInliningReasons)
+ ").");
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
index 2de1eb0..b986800 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
@@ -94,7 +94,8 @@
for (DexEncodedField field : finalLibraryFields) {
if (field.isStatic()) {
feedback.recordLibraryFieldHasAbstractValue(
- field, abstractValueFactory.createSingleFieldValue(field.field, ObjectState.empty()));
+ field,
+ abstractValueFactory.createSingleFieldValue(field.getReference(), ObjectState.empty()));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 5a2f63a..7761bfa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -128,7 +128,7 @@
// field. The requirements for the initialization of this field will be
// checked later.
for (DexEncodedField field : cls.staticFields()) {
- DexType type = field.field.type;
+ DexType type = field.getReference().type;
if (singletonFields.put(type, field) != null) {
// There is already candidate singleton field found.
markNotEligible(type, notEligible);
@@ -137,7 +137,7 @@
// Don't allow fields with this candidate types.
for (DexEncodedField field : cls.instanceFields()) {
- markNotEligible(field.field.type, notEligible);
+ markNotEligible(field.getReference().type, notEligible);
}
// Don't allow methods that take a value of this type.
@@ -192,11 +192,11 @@
private boolean isPinned(DexClass clazz, DexEncodedField singletonField) {
AppInfoWithLiveness appInfo = appView.appInfo();
- if (appInfo.isPinned(clazz.type) || appInfo.isPinned(singletonField.field)) {
+ if (appInfo.isPinned(clazz.type) || appInfo.isPinned(singletonField.getReference())) {
return true;
}
for (DexEncodedMethod method : clazz.methods()) {
- if (!method.isStatic() && appInfo.isPinned(method.method)) {
+ if (!method.isStatic() && appInfo.isPinned(method.getReference())) {
return true;
}
}
@@ -589,7 +589,7 @@
if (invoke.hasOutValue()
&& candidateInfo.getter.get() != null
- && candidateInfo.getter.get().method == invoke.getInvokedMethod()) {
+ && candidateInfo.getter.get().getReference() == invoke.getInvokedMethod()) {
candidateInfo = analyzeAllValueUsers(candidateInfo, invoke.outValue(), false);
}
return candidateInfo;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerGraphLens.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerGraphLens.java
index 75a78ab..c5f6ddc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerGraphLens.java
@@ -7,10 +7,9 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneMap;
-import com.google.common.collect.ImmutableMap;
class ClassStaticizerGraphLens extends NestedGraphLens {
@@ -18,13 +17,7 @@
AppView<?> appView,
BidirectionalOneToOneMap<DexField, DexField> fieldMapping,
BidirectionalOneToOneMap<DexMethod, DexMethod> methodMapping) {
- super(
- ImmutableMap.of(),
- methodMapping.getForwardMap(),
- fieldMapping,
- methodMapping.getInverseOneToOneMap(),
- appView.graphLens(),
- appView.dexItemFactory());
+ super(appView, fieldMapping, methodMapping, EMPTY_TYPE_MAP);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 27806d5..69d65c8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -253,13 +253,15 @@
.filter(
instruction -> {
if (instruction.isStaticGet()
- && instruction.asStaticGet().getField() == info.singletonField.field) {
+ && instruction.asStaticGet().getField()
+ == info.singletonField.getReference()) {
return true;
}
DexEncodedMethod getter = info.getter.get();
return getter != null
&& instruction.isInvokeStatic()
- && instruction.asInvokeStatic().getInvokedMethod() == getter.method;
+ && instruction.asInvokeStatic().getInvokedMethod()
+ == getter.getReference();
})
.collect(Collectors.toList());
boolean fixableFieldReadsPerUsage = true;
@@ -319,10 +321,10 @@
return false;
},
methodsToBeStaticized::add);
- singletonFields.put(candidate.singletonField.field, candidate);
+ singletonFields.put(candidate.singletonField.getReference(), candidate);
DexEncodedMethod getter = candidate.getter.get();
if (getter != null) {
- singletonGetters.put(getter.method, candidate);
+ singletonGetters.put(getter.getReference(), candidate);
}
ProgramMethodSet referencedFrom =
materializedReferencedFromCollections.getOrDefault(candidate, ProgramMethodSet.empty());
@@ -447,7 +449,8 @@
if (newInstance.outValue().hasAnyUsers()) {
TypeElement type = TypeElement.fromDexType(newInstance.clazz, maybeNull(), appView);
newInstance.replace(
- new StaticGet(code.createValue(type), candidateInfo.singletonField.field), code);
+ new StaticGet(code.createValue(type), candidateInfo.singletonField.getReference()),
+ code);
} else {
newInstance.removeOrReplaceByDebugLocalRead(code);
}
@@ -753,11 +756,11 @@
for (DexEncodedMethod method : candidateClass.methods()) {
if (method.isStatic()) {
newDirectMethods.add(method);
- } else if (!factory().isConstructor(method.method)) {
+ } else if (!factory().isConstructor(method.getReference())) {
DexEncodedMethod staticizedMethod = method.toStaticMethodWithoutThis();
newDirectMethods.add(staticizedMethod);
staticizedMethods.createAndAdd(candidateClass, staticizedMethod);
- methodMapping.put(method.method, staticizedMethod.method);
+ methodMapping.put(method.getReference(), staticizedMethod.getReference());
}
}
candidateClass.setVirtualMethods(DexEncodedMethod.EMPTY_ARRAY);
@@ -786,8 +789,9 @@
private boolean classMembersConflict(DexClass a, DexClass b) {
assert Streams.stream(a.methods()).allMatch(DexEncodedMethod::isStatic);
assert a.instanceFields().size() == 0;
- return a.staticFields().stream().anyMatch(fld -> b.lookupField(fld.field) != null)
- || Streams.stream(a.methods()).anyMatch(method -> b.lookupMethod(method.method) != null);
+ return a.staticFields().stream().anyMatch(fld -> b.lookupField(fld.getReference()) != null)
+ || Streams.stream(a.methods())
+ .anyMatch(method -> b.lookupMethod(method.getReference()) != null);
}
private boolean hasMembersNotStaticized(
@@ -818,10 +822,10 @@
List<DexEncodedField> oldFields = hostClass.staticFields();
for (int i = 0; i < oldFields.size(); i++) {
DexEncodedField field = oldFields.get(i);
- DexField newField = mapCandidateField(field.field, candidateClass.type, hostType);
- if (newField != field.field) {
+ DexField newField = mapCandidateField(field.getReference(), candidateClass.type, hostType);
+ if (newField != field.getReference()) {
newFields[i] = field.toTypeSubstitutedField(newField);
- fieldMapping.put(field.field, newField);
+ fieldMapping.put(field.getReference(), newField);
} else {
newFields[i] = field;
}
@@ -830,10 +834,10 @@
List<DexEncodedField> extraFields = candidateClass.staticFields();
for (int i = 0; i < extraFields.size(); i++) {
DexEncodedField field = extraFields.get(i);
- DexField newField = mapCandidateField(field.field, candidateClass.type, hostType);
- if (newField != field.field) {
+ DexField newField = mapCandidateField(field.getReference(), candidateClass.type, hostType);
+ if (newField != field.getReference()) {
newFields[numOfHostStaticFields + i] = field.toTypeSubstitutedField(newField);
- fieldMapping.put(field.field, newField);
+ fieldMapping.put(field.getReference(), newField);
} else {
newFields[numOfHostStaticFields + i] = field;
}
@@ -852,7 +856,8 @@
for (DexEncodedMethod method : extraMethods) {
DexEncodedMethod newMethod =
method.toTypeSubstitutedMethod(
- factory().createMethod(hostType, method.method.proto, method.method.name));
+ factory()
+ .createMethod(hostType, method.getReference().proto, method.getReference().name));
newMethods.add(newMethod);
// If the old method from the candidate class has been staticized,
if (staticizedMethods.remove(method)) {
@@ -860,11 +865,11 @@
// has just been migrated to the host class.
staticizedMethods.createAndAdd(hostClass, newMethod);
}
- DexMethod originalMethod = methodMapping.getRepresentativeKey(method.method);
+ DexMethod originalMethod = methodMapping.getRepresentativeKey(method.getReference());
if (originalMethod == null) {
- methodMapping.put(method.method, newMethod.method);
+ methodMapping.put(method.getReference(), newMethod.getReference());
} else {
- methodMapping.put(originalMethod, newMethod.method);
+ methodMapping.put(originalMethod, newMethod.getReference());
}
}
hostClass.addDirectMethods(newMethods);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
index 5fdaf51..ca49a7d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
@@ -540,7 +540,7 @@
if (contents == null || contents.isEmpty()) {
return;
}
- String result = StringUtils.join(contents, "");
+ String result = StringUtils.join("", contents);
Integer size = Integer.valueOf(contents.size());
Integer length = Integer.valueOf(result.length());
if (isPartial) {
@@ -712,7 +712,7 @@
builder, optimizationConfiguration)) {
return null;
}
- String result = StringUtils.join(contents, "");
+ String result = StringUtils.join("", contents);
int estimate = estimateSizeReduction(contents);
return estimate > result.length() ? result : null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 012bd0e..179dffd 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -609,7 +609,7 @@
if (intervals == null) {
throw new CompilationError(
"Unexpected attempt to get register for a value without a register in method `"
- + code.method().method.toSourceString()
+ + code.method().getReference().toSourceString()
+ "`.",
code.origin);
}
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/RecordGetFieldsAsObjectsCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/RecordGetFieldsAsObjectsCfCodeProvider.java
new file mode 100644
index 0000000..4f534da
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/RecordGetFieldsAsObjectsCfCodeProvider.java
@@ -0,0 +1,102 @@
+// 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.
+
+package com.android.tools.r8.ir.synthetic;
+
+import com.android.tools.r8.cf.code.CfArrayStore;
+import com.android.tools.r8.cf.code.CfConstNumber;
+import com.android.tools.r8.cf.code.CfFieldInstruction;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfLoad;
+import com.android.tools.r8.cf.code.CfNewArray;
+import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfStore;
+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.DexType;
+import com.android.tools.r8.ir.code.MemberType;
+import com.android.tools.r8.ir.code.ValueType;
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Generates a method which answers all field values as an array of objects. If the field value is a
+ * primitive type, it uses the primitive wrapper to wrap it.
+ *
+ * <p>The fields in parameters are in the order where they should be in the array generated by the
+ * method, which is not necessarily the class instanceFields order.
+ *
+ * <p>Example: <code>record Person{ int age; String name;}</code>
+ *
+ * <p><code>Object[] getFieldsAsObjects() {
+ * Object[] fields = new Object[2];
+ * fields[0] = name;
+ * fields[1] = Integer.valueOf(age);
+ * return fields;</code>
+ */
+public class RecordGetFieldsAsObjectsCfCodeProvider extends SyntheticCfCodeProvider {
+
+ public static void registerSynthesizedCodeReferences(DexItemFactory factory) {
+ factory.createSynthesizedType("[Ljava/lang/Object;");
+ factory.primitiveToBoxed.forEach(
+ (primitiveType, boxedType) -> {
+ factory.createSynthesizedType(primitiveType.toDescriptorString());
+ factory.createSynthesizedType(boxedType.toDescriptorString());
+ });
+ }
+
+ private final DexField[] fields;
+
+ public RecordGetFieldsAsObjectsCfCodeProvider(
+ AppView<?> appView, DexType holder, DexField[] fields) {
+ super(appView, holder);
+ this.fields = fields;
+ }
+
+ @Override
+ public CfCode generateCfCode() {
+ // Stack layout:
+ // 0 : receiver (the record instance)
+ // 1 : the array to return
+ // 2+: spills
+ DexItemFactory factory = appView.dexItemFactory();
+ List<CfInstruction> instructions = new ArrayList<>();
+ // Object[] fields = new Object[*length*];
+ instructions.add(new CfConstNumber(fields.length, ValueType.INT));
+ instructions.add(new CfNewArray(factory.objectArrayType));
+ instructions.add(new CfStore(ValueType.OBJECT, 1));
+ // fields[*i*] = this.*field* || *PrimitiveWrapper*.valueOf(this.*field*);
+ for (int i = 0; i < fields.length; i++) {
+ DexField field = fields[i];
+ instructions.add(new CfLoad(ValueType.OBJECT, 1));
+ instructions.add(new CfConstNumber(i, ValueType.INT));
+ instructions.add(new CfLoad(ValueType.OBJECT, 0));
+ instructions.add(new CfFieldInstruction(Opcodes.GETFIELD, field, field));
+ if (field.type.isPrimitiveType()) {
+ factory.primitiveToBoxed.forEach(
+ (primitiveType, boxedType) -> {
+ if (primitiveType == field.type) {
+ instructions.add(
+ new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(
+ boxedType,
+ factory.createProto(boxedType, primitiveType),
+ factory.valueOfMethodName),
+ false));
+ }
+ });
+ }
+ instructions.add(new CfArrayStore(MemberType.OBJECT));
+ }
+ // return fields;
+ instructions.add(new CfLoad(ValueType.OBJECT, 1));
+ instructions.add(new CfReturn(ValueType.OBJECT));
+ return standardCfCodeFromInstructions(instructions);
+ }
+}
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 1587e8a..5ade4de 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -218,9 +218,9 @@
if (clazz.isRecord()) {
// TODO(b/169645628): Strip record components if not kept.
for (DexEncodedField instanceField : clazz.instanceFields()) {
- String componentName = namingLens.lookupName(instanceField.field).toString();
+ String componentName = namingLens.lookupName(instanceField.getReference()).toString();
String componentDescriptor =
- namingLens.lookupDescriptor(instanceField.field.type).toString();
+ namingLens.lookupDescriptor(instanceField.getReference().type).toString();
String componentSignature =
instanceField.getGenericSignature().toRenamedString(namingLens, isTypeMissing);
writer.visitRecordComponent(componentName, componentDescriptor, componentSignature);
@@ -239,7 +239,9 @@
}
if (options.desugarSpecificOptions().sortMethodsOnCfOutput) {
SortedSet<ProgramMethod> programMethodSortedSet =
- Sets.newTreeSet((a, b) -> a.getDefinition().method.compareTo(b.getDefinition().method));
+ Sets.newTreeSet(
+ (a, b) ->
+ a.getDefinition().getReference().compareTo(b.getDefinition().getReference()));
clazz.forEachProgramMethod(programMethodSortedSet::add);
programMethodSortedSet.forEach(
method -> writeMethod(method, version, rewriter, writer, defaults));
@@ -268,7 +270,7 @@
// In this case bridges have been introduced for the Cf back-end,
// which do not have class file version.
assert options.isDesugaredLibraryCompilation() || options.cfToCfDesugar
- : "Expected class file version for " + method.method.toSourceString();
+ : "Expected class file version for " + method.getReference().toSourceString();
assert MIN_VERSION_FOR_COMPILER_GENERATED_CODE.isLessThan(
options.classFileVersionAfterDesugaring(InternalOptions.SUPPORTED_CF_VERSION));
// Any desugaring rewrites which cannot meet the default class file version after
@@ -355,8 +357,8 @@
if (field.isDeprecated()) {
access = AsmUtils.withDeprecated(access);
}
- String name = namingLens.lookupName(field.field).toString();
- String desc = namingLens.lookupDescriptor(field.field.type).toString();
+ String name = namingLens.lookupName(field.getReference()).toString();
+ String desc = namingLens.lookupDescriptor(field.getReference().type).toString();
String signature = field.getGenericSignature().toRenamedString(namingLens, isTypeMissing);
Object value = getStaticValue(field);
FieldVisitor visitor = writer.visitField(access, name, desc, signature, value);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
index d9baf1f..f10902f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
@@ -93,11 +93,11 @@
Consumer<DexEncodedMethod> keepByteCode) {
Map<String, DexEncodedField> fieldMap = new HashMap<>();
for (DexEncodedField field : hostClass.fields()) {
- fieldMap.put(toJvmFieldSignature(field.field).asString(), field);
+ fieldMap.put(toJvmFieldSignature(field.getReference()).asString(), field);
}
Map<String, DexEncodedMethod> methodMap = new HashMap<>();
for (DexEncodedMethod method : hostClass.methods()) {
- methodMap.put(toJvmMethodSignature(method.method).asString(), method);
+ methodMap.put(toJvmMethodSignature(method.getReference()).asString(), method);
}
ImmutableList.Builder<KotlinConstructorInfo> notBackedConstructors = ImmutableList.builder();
for (KmConstructor kmConstructor : kmClass.getConstructors()) {
@@ -184,7 +184,7 @@
return;
}
for (DexEncodedField field : hostClass.fields()) {
- if (field.field.name.toString().equals(companionObjectName)) {
+ if (field.getReference().name.toString().equals(companionObjectName)) {
field.setKotlinMemberInfo(new KotlinCompanionInfo());
return;
}
@@ -221,7 +221,10 @@
// Find a companion object.
for (DexEncodedField field : clazz.fields()) {
if (field.getKotlinMemberInfo().isCompanion()) {
- field.getKotlinMemberInfo().asCompanion().rewrite(kmClass, field.field, namingLens);
+ field
+ .getKotlinMemberInfo()
+ .asCompanion()
+ .rewrite(kmClass, field.getReference(), namingLens);
}
}
// Take all not backed constructors because we will never find them in definitions.
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
index 79b4173..7447bbd 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
@@ -184,7 +184,7 @@
}
KotlinPropertyGroup kotlinPropertyGroup =
properties.computeIfAbsent(kotlinPropertyInfo, ignored -> new KotlinPropertyGroup());
- if (method.method.proto.returnType == appView.dexItemFactory().voidType) {
+ if (method.getReference().proto.returnType == appView.dexItemFactory().voidType) {
// This is a setter.
kotlinPropertyGroup.setSetter(method);
} else {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
index f5ce062..008177e 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
@@ -114,8 +114,8 @@
// TODO(b/154348683): Check method for flags to pass in.
String finalName = this.name;
if (method != null) {
- String methodName = method.method.name.toString();
- String rewrittenName = namingLens.lookupName(method.method).toString();
+ String methodName = method.getReference().name.toString();
+ String rewrittenName = namingLens.lookupName(method.getReference()).toString();
if (!methodName.equals(rewrittenName)) {
finalName = rewrittenName;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
index 974e4a8..2606807 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
@@ -40,8 +40,8 @@
DexEncodedField field, AppView<?> appView, NamingLens namingLens) {
String finalName = name;
if (field != null) {
- String fieldName = field.field.name.toString();
- String rewrittenName = namingLens.lookupName(field.field).toString();
+ String fieldName = field.getReference().name.toString();
+ String rewrittenName = namingLens.lookupName(field.getReference()).toString();
if (!fieldName.equals(rewrittenName)) {
finalName = rewrittenName;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
index 2469a54..b0314be 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
@@ -79,8 +79,8 @@
assert returnType != null;
String finalName = name;
if (method != null) {
- String methodName = method.method.name.toString();
- String rewrittenName = namingLens.lookupName(method.method).toString();
+ String methodName = method.getReference().name.toString();
+ String rewrittenName = namingLens.lookupName(method.getReference()).toString();
if (!methodName.equals(rewrittenName)) {
finalName = rewrittenName;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
index cc215d5..01a7c2a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
@@ -40,7 +40,7 @@
JvmMethodSignature signature = JvmExtensionsKt.getSignature(lambda.function);
if (signature != null) {
for (DexEncodedMethod method : clazz.methods()) {
- if (toJvmMethodSignature(method.method).asString().equals(signature.asString())) {
+ if (toJvmMethodSignature(method.getReference()).asString().equals(signature.asString())) {
method.setKotlinMemberInfo(kotlinFunctionInfo);
return new KotlinLambdaInfo(kotlinFunctionInfo, true);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index 1e3273c..4a5904e 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -182,7 +182,10 @@
if (kotlinMetadata == null || kotlinMetadata.isNotProgramClass()) {
return true;
}
- return kotlinMetadata.methods(method -> method.method.name == fieldName).iterator().hasNext();
+ return kotlinMetadata
+ .methods(method -> method.getReference().name == fieldName)
+ .iterator()
+ .hasNext();
}
private DexAnnotation createKotlinMetadataAnnotation(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java
index ca1d394..fbfb3bb 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java
@@ -110,7 +110,7 @@
KotlinClassMetadata.MultiFileClassFacade kMetadata, String indent) {
return indent
+ "MetaData.MultiFileClassFacade("
- + StringUtils.join(kMetadata.getPartClassNames(), ", ")
+ + StringUtils.join(", ", kMetadata.getPartClassNames())
+ ")";
}
@@ -327,16 +327,16 @@
});
String companionObject = kmClass.getCompanionObject();
appendKeyValue(
- indent, "enumEntries", sb, "[" + StringUtils.join(kmClass.getEnumEntries(), ",") + "]");
+ indent, "enumEntries", sb, "[" + StringUtils.join(",", kmClass.getEnumEntries()) + "]");
appendKeyValue(
indent, "companionObject", sb, companionObject == null ? "null" : companionObject);
appendKeyValue(
indent,
"sealedSubclasses",
sb,
- "[" + StringUtils.join(kmClass.getSealedSubclasses(), ",") + "]");
+ "[" + StringUtils.join(",", kmClass.getSealedSubclasses()) + "]");
appendKeyValue(
- indent, "nestedClasses", sb, "[" + StringUtils.join(kmClass.getNestedClasses(), ",") + "]");
+ indent, "nestedClasses", sb, "[" + StringUtils.join(",", kmClass.getNestedClasses()) + "]");
appendKeyValue(
indent,
"anonymousObjectOriginName",
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
index 1ac03db..41ff17d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
@@ -47,11 +47,11 @@
Consumer<DexEncodedMethod> keepByteCode) {
Map<String, DexEncodedField> fieldMap = new HashMap<>();
for (DexEncodedField field : clazz.fields()) {
- fieldMap.put(toJvmFieldSignature(field.field).asString(), field);
+ fieldMap.put(toJvmFieldSignature(field.getReference()).asString(), field);
}
Map<String, DexEncodedMethod> methodMap = new HashMap<>();
for (DexEncodedMethod method : clazz.methods()) {
- methodMap.put(toJvmMethodSignature(method.method).asString(), method);
+ methodMap.put(toJvmMethodSignature(method.getReference()).asString(), method);
}
return new KotlinPackageInfo(
JvmExtensionsKt.getModuleName(kmPackage),
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 1b91b62..9ab6c15 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -152,11 +152,11 @@
}
private void renameDanglingTypesInField(DexEncodedField field) {
- renameDanglingType(field.field.type);
+ renameDanglingType(field.getReference().type);
}
private void renameDanglingTypesInMethod(DexEncodedMethod method) {
- DexProto proto = method.method.proto;
+ DexProto proto = method.getReference().proto;
renameDanglingType(proto.returnType);
for (DexType type : proto.parameters.values) {
renameDanglingType(type);
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index 55ed725..bec8073 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -106,10 +106,10 @@
reservedNames = getOrCreateReservedFieldNamingState(clazz.type);
}
reservedNames.markReservedDirectly(
- reservedName, field.field.name, field.field.type);
+ reservedName, field.getReference().name, field.getReference().type);
// TODO(b/148846065): Consider lazily computing the renaming on actual lookups.
- if (reservedName != field.field.name) {
- renaming.put(field.field, reservedName);
+ if (reservedName != field.getReference().name) {
+ renaming.put(field.getReference(), reservedName);
}
}
}
@@ -135,8 +135,8 @@
clazz -> {
for (DexEncodedField field : clazz.fields()) {
DexString reservedName = strategy.getReservedName(field, clazz);
- if (reservedName != null && reservedName != field.field.name) {
- renaming.put(field.field, reservedName);
+ if (reservedName != null && reservedName != field.getReference().name) {
+ renaming.put(field.getReference(), reservedName);
}
}
});
@@ -270,8 +270,10 @@
return;
}
DexEncodedField definition = appView.appInfo().resolveFieldOn(holder, field).getResolvedField();
- if (definition != null && definition.field != field && renaming.containsKey(definition.field)) {
- renaming.put(field, renaming.get(definition.field));
+ if (definition != null
+ && definition.getReference() != field
+ && renaming.containsKey(definition.getReference())) {
+ renaming.put(field, renaming.get(definition.getReference()));
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
index 2d9a19d..e0de1d5 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
@@ -74,7 +74,7 @@
private void decoupleIdentifierNameStringInStaticField(DexEncodedField encodedField) {
assert encodedField.accessFlags.isStatic();
- if (!identifierNameStrings.containsKey(encodedField.field)) {
+ if (!identifierNameStrings.containsKey(encodedField.getReference())) {
return;
}
DexValueString staticValue = encodedField.getStaticValue().asDexValueString();
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
index 01157b9..3e4078b 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
@@ -378,9 +378,9 @@
private static DexField inferFieldInHolder(DexClass holder, String name, DexType fieldType) {
for (DexEncodedField encodedField : holder.fields()) {
- if (encodedField.field.name.toString().equals(name)
- && (fieldType == null || encodedField.field.type == fieldType)) {
- return encodedField.field;
+ if (encodedField.getReference().name.toString().equals(name)
+ && (fieldType == null || encodedField.getReference().type == fieldType)) {
+ return encodedField.getReference();
}
}
return null;
@@ -388,8 +388,8 @@
private static DexMethod inferMethodNameInHolder(DexClass holder, String name) {
for (DexEncodedMethod encodedMethod : holder.methods()) {
- if (encodedMethod.method.name.toString().equals(name)) {
- return encodedMethod.method;
+ if (encodedMethod.getReference().name.toString().equals(name)) {
+ return encodedMethod.getReference();
}
}
return null;
@@ -399,9 +399,9 @@
DexClass holder, String name, DexTypeList arguments) {
assert arguments != null;
for (DexEncodedMethod encodedMethod : holder.methods()) {
- if (encodedMethod.method.name.toString().equals(name)
- && encodedMethod.method.proto.parameters.equals(arguments)) {
- return encodedMethod.method;
+ if (encodedMethod.getReference().name.toString().equals(name)
+ && encodedMethod.getReference().proto.parameters.equals(arguments)) {
+ return encodedMethod.getReference();
}
}
return null;
diff --git a/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java
index 0f5924d..3ba2467 100644
--- a/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java
@@ -483,7 +483,8 @@
boolean differentName = implementedMethod.getName() != virtualMethod.getName();
if (differentName
&& MethodJavaSignatureEquivalence.getEquivalenceIgnoreName()
- .equivalent(implementedMethod.method, virtualMethod.method)) {
+ .equivalent(
+ implementedMethod.getReference(), virtualMethod.getReference())) {
InterfaceMethodGroupState interfaceMethodGroupState =
globalStateMap.computeIfAbsent(
definitionEquivalence.wrap(implementedMethod),
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
index eb4e9ca..a51edde 100644
--- a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
@@ -96,7 +96,7 @@
// If the method does not have a direct renaming, return the resolutions mapping.
ResolutionResult resolutionResult = appView.appInfo().unsafeResolveMethodDueToDexFormat(method);
if (resolutionResult.isSingleResolution()) {
- return renaming.getOrDefault(resolutionResult.getSingleTarget().method, method.name);
+ return renaming.getOrDefault(resolutionResult.getSingleTarget().getReference(), method.name);
}
// If resolution fails, the method must be renamed consistently with the targets that give rise
// to the failure.
@@ -104,8 +104,9 @@
List<DexEncodedMethod> targets = new ArrayList<>();
resolutionResult.asFailedResolution().forEachFailureDependency(targets::add);
if (!targets.isEmpty()) {
- DexString firstRename = renaming.get(targets.get(0).method);
- assert targets.stream().allMatch(target -> renaming.get(target.method) == firstRename);
+ DexString firstRename = renaming.get(targets.get(0).getReference());
+ assert targets.stream()
+ .allMatch(target -> renaming.get(target.getReference()) == firstRename);
if (firstRename != null) {
return firstRename;
}
@@ -138,7 +139,7 @@
// If we can resolve `item`, then the renaming for `item` and its resolution should be the
// same.
DexEncodedMethod resolvedMethod = resolution.asSingleResolution().getResolvedMethod();
- assert lookupName(method) == lookupName(resolvedMethod.method);
+ assert lookupName(method) == lookupName(resolvedMethod.getReference());
return true;
}
@@ -162,7 +163,7 @@
.asFailedResolution()
.forEachFailureDependency(
failureDependence -> {
- assert lookupName(method) == lookupName(failureDependence.method);
+ assert lookupName(method) == lookupName(failureDependence.getReference());
});
return true;
}
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index c00993f..a542a2f 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -260,22 +260,24 @@
if (!allowMemberRenaming(holder)
|| holder.accessFlags.isAnnotation()
|| method.accessFlags.isConstructor()
- || !appView.appInfo().isMinificationAllowed(method.method)) {
- return method.method.name;
+ || !appView.appInfo().isMinificationAllowed(method.getReference())) {
+ return method.getReference().name;
}
if (desugaredLibraryRenaming
&& method.isLibraryMethodOverride().isTrue()
- && appView.rewritePrefix.hasRewrittenTypeInSignature(method.method.proto, appView)) {
+ && appView.rewritePrefix.hasRewrittenTypeInSignature(
+ method.getReference().proto, appView)) {
// With desugared library, call-backs names are reserved here.
- return method.method.name;
+ return method.getReference().name;
}
return null;
}
@Override
public DexString getReservedName(DexEncodedField field, DexClass holder) {
- if (holder.isLibraryClass() || !appView.appInfo().isMinificationAllowed(field.field)) {
- return field.field.name;
+ if (holder.isLibraryClass()
+ || !appView.appInfo().isMinificationAllowed(field.getReference())) {
+ return field.getReference().name;
}
return null;
}
diff --git a/src/main/java/com/android/tools/r8/naming/NamingLens.java b/src/main/java/com/android/tools/r8/naming/NamingLens.java
index bdd0e70..b6e94ee 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingLens.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingLens.java
@@ -166,14 +166,14 @@
}
for (DexEncodedField field : clazz.fields()) {
- DexField newField = lookupField(field.field, dexItemFactory);
+ DexField newField = lookupField(field.getReference(), dexItemFactory);
boolean referencesChanged = references.add(newField);
assert referencesChanged
: "Duplicate definition of field `" + newField.toSourceString() + "`";
}
for (DexEncodedMethod method : clazz.methods()) {
- DexMethod newMethod = lookupMethod(method.method, dexItemFactory);
+ DexMethod newMethod = lookupMethod(method.getReference(), dexItemFactory);
boolean referencesChanged = references.add(newMethod);
assert referencesChanged
: "Duplicate definition of method `" + newMethod.toSourceString() + "`";
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index b75956e..a8e299a 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.naming;
import static com.android.tools.r8.graph.DexApplication.classesWithDeterministicOrder;
+import static com.android.tools.r8.utils.IterableUtils.fromMethod;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -51,7 +52,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiPredicate;
-import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -99,19 +99,17 @@
timing.begin("MappingInterfaces");
Set<DexClass> interfaces = new TreeSet<>(Comparator.comparing(DexClass::getType));
- Consumer<DexClass> consumer =
- clazz -> {
- if (clazz.isInterface()) {
- // Only visit top level interfaces because computeMapping will visit the hierarchy.
- if (clazz.interfaces.isEmpty()) {
- computeMapping(clazz.type, nonPrivateMembers, notMappedReferences, subtypingInfo);
- }
- interfaces.add(clazz);
- }
- };
// For union-find of interface methods we also need to add the library types above live types.
- appInfo.forEachTypeInHierarchyOfLiveProgramClasses(consumer);
- appInfo.forEachReferencedClasspathClass(consumer::accept);
+ appInfo.forEachReachableInterface(
+ iFace -> {
+ assert iFace.isInterface();
+ interfaces.add(iFace);
+ if (iFace.interfaces.isEmpty()) {
+ computeMapping(iFace.type, nonPrivateMembers, notMappedReferences, subtypingInfo);
+ }
+ },
+ fromMethod(appInfo::forEachReferencedClasspathClass, DexClass::getType));
+
assert nonPrivateMembers.isEmpty();
timing.end();
@@ -504,12 +502,12 @@
@Override
public DexString getReservedName(DexEncodedMethod method, DexClass holder) {
- return getReservedName(method, method.method.name, holder);
+ return getReservedName(method, method.getReference().name, holder);
}
@Override
public DexString getReservedName(DexEncodedField field, DexClass holder) {
- return getReservedName(field, field.field.name, holder);
+ return getReservedName(field, field.getReference().name, holder);
}
private DexString getReservedName(DexDefinition definition, DexString name, DexClass holder) {
diff --git a/src/main/java/com/android/tools/r8/naming/RecordRewritingNamingLens.java b/src/main/java/com/android/tools/r8/naming/RecordRewritingNamingLens.java
index 83fa84e..e809317 100644
--- a/src/main/java/com/android/tools/r8/naming/RecordRewritingNamingLens.java
+++ b/src/main/java/com/android/tools/r8/naming/RecordRewritingNamingLens.java
@@ -45,7 +45,7 @@
private DexString getRenaming(DexType type) {
if (type == factory.recordType) {
- return factory.r8RecordType.descriptor;
+ return factory.recordTagType.descriptor;
}
return null;
}
@@ -77,7 +77,7 @@
@Override
public DexString lookupDescriptorForJavaTypeName(String typeName) {
if (typeName.equals(factory.recordType.toSourceString())) {
- return factory.r8RecordType.descriptor;
+ return factory.recordTagType.descriptor;
}
return namingLens.lookupDescriptorForJavaTypeName(typeName);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java b/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
index a675776..dd67f3a 100644
--- a/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
@@ -167,14 +167,16 @@
if (accessFlags.isPackagePrivate()) {
// If we publicize a package private method we have to ensure there is no overrides of it. We
- // could potentially publicize a method if it only has package-private overrides, but for know
- // we just check if it is seen below.
- // Note that we will not publize private methods if there exists a package-private override,
- // and there is therefore no need to check the hierarchy above.
+ // could potentially publicize a method if it only has package-private overrides.
+ // TODO(b/182136236): See if we can break the hierarchy for clusters.
MemberPool<DexMethod> memberPool = methodPoolCollection.get(method.getHolder());
Wrapper<DexMethod> methodKey = MethodSignatureEquivalence.get().wrap(method.getReference());
- if (memberPool.hasSeenStrictlyBelow(methodKey)
- && appView.options().enablePackagePrivateAwarePublicization) {
+ if (memberPool.below(
+ methodKey,
+ false,
+ true,
+ (clazz, ignored) ->
+ !method.getContextType().getPackageName().equals(clazz.getType().getPackageName()))) {
return false;
}
doPublicize(method);
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 04a24b6..2b9252f 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -188,11 +188,11 @@
DexEncodedMethod target = lookupTarget.apply(method);
// TODO(b/128404854) Rebind to the lowest library class or program class. For now we allow
// searching in library for methods, but this should be done on classpath instead.
- if (target == null || target.method == method) {
+ if (target == null || target.getReference() == method) {
return;
}
DexClass targetClass = appView.definitionFor(target.getHolderType());
- DexMethod targetMethod = target.method;
+ DexMethod targetMethod = target.getReference();
if (originalClass.isProgramClass()) {
// In Java bytecode, it is only possible to target interface methods that are in one of
// the immediate super-interfaces via a super-invocation (see
@@ -235,7 +235,7 @@
target.toForwardingMethod(bridgeHolder, appView);
bridgeHolder.addMethod(bridgeMethodDefinition);
}
- assert lookupTarget.apply(method).method == bridgeMethod;
+ assert lookupTarget.apply(method).getReference() == bridgeMethod;
}
});
}
@@ -267,7 +267,7 @@
assert bridgeHolder != null;
assert bridgeHolder != targetClass;
bridges.accept(bridgeHolder, method, target);
- return target.method.withHolder(bridgeHolder.getType(), appView.dexItemFactory());
+ return target.getReference().withHolder(bridgeHolder.getType(), appView.dexItemFactory());
}
private DexProgramClass findHolderForInterfaceMethodBridge(DexProgramClass clazz, DexType iface) {
@@ -316,9 +316,9 @@
findHolderForVisibilityBridge(originalClass, targetClass, packageDescriptor);
assert bridgeHolder != null;
bridges.accept(bridgeHolder, method, target);
- return target.method.withHolder(bridgeHolder.getType(), appView.dexItemFactory());
+ return target.getReference().withHolder(bridgeHolder.getType(), appView.dexItemFactory());
}
- return target.method;
+ return target.getReference();
}
private DexProgramClass findHolderForVisibilityBridge(
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
index 171dcbe..4310236 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.optimize;
-import static com.android.tools.r8.graph.GraphLens.NestedGraphLens.mapVirtualInterfaceInvocationTypes;
+import static com.android.tools.r8.graph.NestedGraphLens.mapVirtualInterfaceInvocationTypes;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
diff --git a/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java b/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
index 8ea4e1f..322ccb1 100644
--- a/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
@@ -8,10 +8,8 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLens;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.ir.code.Invoke.Type;
-import com.android.tools.r8.utils.collections.EmptyBidirectionalOneToOneMap;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import java.util.Set;
@@ -21,13 +19,7 @@
private final Set<DexMethod> publicizedMethods;
private PublicizerLens(AppView<?> appView, Set<DexMethod> publicizedMethods) {
- super(
- ImmutableMap.of(),
- ImmutableMap.of(),
- new EmptyBidirectionalOneToOneMap<>(),
- new EmptyBidirectionalOneToOneMap<>(),
- appView.graphLens(),
- appView.dexItemFactory());
+ super(appView, EMPTY_FIELD_MAP, EMPTY_METHOD_MAP, EMPTY_TYPE_MAP);
this.appView = appView;
this.publicizedMethods = publicizedMethods;
}
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 96dd07b..f073314 100644
--- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
@@ -87,7 +87,10 @@
if (targetMethod != null && targetMethod.accessFlags.isPublic()) {
if (Log.ENABLED) {
Log.info(
- getClass(), "Removing visibility forwarding %s -> %s", method, targetMethod.method);
+ getClass(),
+ "Removing visibility forwarding %s -> %s",
+ method,
+ targetMethod.getReference());
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
index ea4ee0e..69c59b5 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
@@ -140,7 +140,7 @@
for (DexEncodedMethod method : subclass.virtualMethods()) {
BridgeInfo bridgeInfo = method.getOptimizationInfo().getBridgeInfo();
if (bridgeInfo != null) {
- candidates.add(equivalence.wrap(method.method));
+ candidates.add(equivalence.wrap(method.getReference()));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingResult.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingResult.java
index 4439aea..e1311d5 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingResult.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingResult.java
@@ -23,7 +23,7 @@
// Mapping from non-hoisted bridge methods to hoisted bridge methods.
private final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod>
- bridgeToHoistedBridgeMap = new BidirectionalManyToOneRepresentativeHashMap<>();
+ bridgeToHoistedBridgeMap = BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
BridgeHoistingResult(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
diff --git a/src/main/java/com/android/tools/r8/references/MethodReference.java b/src/main/java/com/android/tools/r8/references/MethodReference.java
index 9ff0649..fc8f183 100644
--- a/src/main/java/com/android/tools/r8/references/MethodReference.java
+++ b/src/main/java/com/android/tools/r8/references/MethodReference.java
@@ -77,7 +77,7 @@
public String getMethodDescriptor() {
return StringUtils.join(
- ListUtils.map(getFormalTypes(), TypeReference::getDescriptor), "", BraceType.PARENS)
+ "", ListUtils.map(getFormalTypes(), TypeReference::getDescriptor), BraceType.PARENS)
+ (getReturnType() == null ? "V" : getReturnType().getDescriptor());
}
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
index e6d16eb..64fe0eb 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
@@ -10,7 +10,7 @@
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.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
@@ -22,23 +22,17 @@
public class RepackagingLens extends NestedGraphLens {
- private final BiMap<DexType, DexType> originalTypes;
+ private final BiMap<DexType, DexType> newTypes;
private final Map<String, String> packageRenamings;
private RepackagingLens(
AppView<AppInfoWithLiveness> appView,
BidirectionalOneToOneMap<DexField, DexField> newFieldSignatures,
- BidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures,
- BiMap<DexType, DexType> originalTypes,
+ BidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures,
+ BiMap<DexType, DexType> newTypes,
Map<String, String> packageRenamings) {
- super(
- originalTypes.inverse(),
- originalMethodSignatures.getInverseOneToOneMap().getForwardMap(),
- newFieldSignatures,
- originalMethodSignatures,
- appView.graphLens(),
- appView.dexItemFactory());
- this.originalTypes = originalTypes;
+ super(appView, newFieldSignatures, newMethodSignatures, newTypes);
+ this.newTypes = newTypes;
this.packageRenamings = packageRenamings;
}
@@ -49,7 +43,7 @@
@Override
public DexType getOriginalType(DexType type) {
- DexType previous = originalTypes.getOrDefault(type, type);
+ DexType previous = newTypes.inverse().getOrDefault(type, type);
return getPrevious().getOriginalType(previous);
}
@@ -73,7 +67,7 @@
}
private boolean isSimpleTypeRenamingOrEqual(DexType from, DexType to) {
- return from == to || originalTypes.get(to) == from;
+ return from == to || newTypes.get(from) == to;
}
private boolean isSimpleTypeRenamingOrEqual(DexMember<?, ?> from, DexMember<?, ?> to) {
@@ -82,16 +76,16 @@
}
return IterableUtils.testPairs(
this::isSimpleTypeRenamingOrEqual,
- from.getReferencedBaseTypes(dexItemFactory),
- to.getReferencedBaseTypes(dexItemFactory));
+ from.getReferencedBaseTypes(dexItemFactory()),
+ to.getReferencedBaseTypes(dexItemFactory()));
}
public static class Builder {
- protected final BiMap<DexType, DexType> originalTypes = HashBiMap.create();
+ protected final BiMap<DexType, DexType> newTypes = HashBiMap.create();
protected final MutableBidirectionalOneToOneMap<DexField, DexField> newFieldSignatures =
new BidirectionalOneToOneHashMap<>();
- protected final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures =
+ protected final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures =
new BidirectionalOneToOneHashMap<>();
public void recordMove(DexField from, DexField to) {
@@ -99,18 +93,18 @@
}
public void recordMove(DexMethod from, DexMethod to) {
- originalMethodSignatures.put(to, from);
+ newMethodSignatures.put(from, to);
}
public void recordMove(DexType from, DexType to) {
- originalTypes.put(to, from);
+ newTypes.put(from, to);
}
public RepackagingLens build(
AppView<AppInfoWithLiveness> appView, Map<String, String> packageRenamings) {
- assert !originalTypes.isEmpty();
+ assert !newTypes.isEmpty();
return new RepackagingLens(
- appView, newFieldSignatures, originalMethodSignatures, originalTypes, packageRenamings);
+ appView, newFieldSignatures, newMethodSignatures, newTypes, packageRenamings);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
index b64646d..4123c10 100644
--- a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
@@ -64,7 +64,7 @@
DexEncodedMethod method = virtualMethods.get(i);
if (scope.addMethodIfMoreVisible(method) != AddMethodIfMoreVisibleResult.NOT_ADDED
|| !method.accessFlags.isAbstract()
- || appView.appInfo().isPinned(method.method)) {
+ || appView.appInfo().isPinned(method.getReference())) {
if (methods != null) {
methods.add(method);
}
@@ -76,7 +76,7 @@
}
}
if (Log.ENABLED) {
- Log.debug(getClass(), "Removing abstract method %s.", method.method);
+ Log.debug(getClass(), "Removing abstract method %s.", method.getReference());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 057a80f..34c11ee 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -254,7 +254,7 @@
boolean liveGetter =
definition
.getMethodCollection()
- .hasVirtualMethods(method -> method.method.name == original.name);
+ .hasVirtualMethods(method -> method.getReference().name == original.name);
return liveGetter ? original : null;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index b186a52..4622786 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -59,6 +59,7 @@
import com.android.tools.r8.utils.WorkList;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.structural.Ordered;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
@@ -662,7 +663,13 @@
}
public void forEachReachableInterface(Consumer<DexClass> consumer) {
+ forEachReachableInterface(consumer, ImmutableList.of());
+ }
+
+ public void forEachReachableInterface(
+ Consumer<DexClass> consumer, Iterable<DexType> additionalPaths) {
WorkList<DexType> worklist = WorkList.newIdentityWorkList();
+ worklist.addIfNotSeen(additionalPaths);
worklist.addIfNotSeen(objectAllocationInfoCollection.getInstantiatedLambdaInterfaces());
for (DexProgramClass clazz : classes()) {
worklist.addIfNotSeen(clazz.type);
@@ -676,10 +683,7 @@
if (definition.isInterface()) {
consumer.accept(definition);
}
- if (definition.superType != null) {
- worklist.addIfNotSeen(definition.superType);
- }
- worklist.addIfNotSeen(definition.interfaces.values);
+ definition.forEachImmediateSupertype(worklist::addIfNotSeen);
}
}
@@ -727,7 +731,7 @@
}
assert clazz.isInterface();
for (DexEncodedMethod method : clazz.virtualMethods()) {
- if (method.method.name == callSite.methodName && method.accessFlags.isAbstract()) {
+ if (method.getReference().name == callSite.methodName && method.accessFlags.isAbstract()) {
result.add(method);
}
}
@@ -806,7 +810,7 @@
public boolean isFieldRead(DexEncodedField encodedField) {
assert checkIfObsolete();
- DexField field = encodedField.field;
+ DexField field = encodedField.getReference();
FieldAccessInfo info = getFieldAccessInfoCollection().get(field);
if (info != null && info.isRead()) {
return true;
@@ -820,12 +824,13 @@
public boolean isFieldWritten(DexEncodedField encodedField) {
assert checkIfObsolete();
- return isFieldWrittenByFieldPutInstruction(encodedField) || isPinned(encodedField.field);
+ return isFieldWrittenByFieldPutInstruction(encodedField)
+ || isPinned(encodedField.getReference());
}
public boolean isFieldWrittenByFieldPutInstruction(DexEncodedField encodedField) {
assert checkIfObsolete();
- DexField field = encodedField.field;
+ DexField field = encodedField.getReference();
FieldAccessInfo info = getFieldAccessInfoCollection().get(field);
if (info != null && info.isWritten()) {
// The field is written directly by the program itself.
@@ -838,7 +843,7 @@
public boolean isFieldOnlyWrittenInMethod(DexEncodedField field, DexEncodedMethod method) {
assert checkIfObsolete();
assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
- if (isPinned(field.field)) {
+ if (isPinned(field.getReference())) {
return false;
}
return isFieldOnlyWrittenInMethodIgnoringPinning(field, method);
@@ -848,7 +853,7 @@
DexEncodedField field, DexEncodedMethod method) {
assert checkIfObsolete();
assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
- FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.field);
+ FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.getReference());
return fieldAccessInfo != null
&& fieldAccessInfo.isWritten()
&& !fieldAccessInfo.isWrittenOutside(method);
@@ -857,10 +862,10 @@
public boolean isInstanceFieldWrittenOnlyInInstanceInitializers(DexEncodedField field) {
assert checkIfObsolete();
assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
- if (isPinned(field.field)) {
+ if (isPinned(field.getReference())) {
return false;
}
- FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.field);
+ FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.getReference());
if (fieldAccessInfo == null || !fieldAccessInfo.isWritten()) {
return false;
}
@@ -995,7 +1000,7 @@
DexProgramClass clazz = asProgramClassOrNull(definitionFor(type));
if (clazz != null) {
for (DexEncodedMethod method : clazz.directMethods()) {
- if (method.isInstanceInitializer() && isPinned(method.method)) {
+ if (method.isInstanceInitializer() && isPinned(method.getReference())) {
return true;
}
}
@@ -1267,7 +1272,7 @@
if (refinedReceiverClass.isProgramClass()) {
DexClassAndMethod clazzAndMethod =
resolution.lookupVirtualDispatchTarget(refinedReceiverClass.asProgramClass(), this);
- if (clazzAndMethod == null || isPinned(clazzAndMethod.getDefinition().method)) {
+ if (clazzAndMethod == null || isPinned(clazzAndMethod.getDefinition().getReference())) {
// TODO(b/150640456): We should maybe only consider program methods.
return DexEncodedMethod.SENTINEL;
}
@@ -1279,7 +1284,7 @@
// implementation, but we use this for library modelling.
DexEncodedMethod resolvedMethod = resolution.getResolvedMethod();
DexEncodedMethod targetOnReceiver =
- refinedReceiverClass.lookupVirtualMethod(resolvedMethod.method);
+ refinedReceiverClass.lookupVirtualMethod(resolvedMethod.getReference());
if (targetOnReceiver != null && isOverriding(resolvedMethod, targetOnReceiver)) {
return targetOnReceiver;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java b/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
index f032832..03611d6 100644
--- a/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
@@ -54,7 +54,7 @@
}
// When compiling for dex, we can't use wide fields since we've only allocated a single
// register for the out-value of each ClassInit instruction
- if (staticField.field.type.isWideType()) {
+ if (staticField.getReference().type.isWideType()) {
continue;
}
if (encodedClinitField == null) {
@@ -90,7 +90,7 @@
d8R8Synthesized);
clazz.appendStaticField(encodedClinitField);
}
- lensBuilder.map(type, encodedClinitField.field);
+ lensBuilder.map(type, encodedClinitField.getReference());
}
private boolean isMinimumRequiredVisibility(
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index e818526..331466b 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -929,17 +929,17 @@
}
// Check if we have previously created a FieldAccessInfo object for the field definition.
- info = fieldAccessInfoCollection.get(encodedField.field);
+ info = fieldAccessInfoCollection.get(encodedField.getReference());
// If not, we must create one.
if (info == null) {
- info = new FieldAccessInfoImpl(encodedField.field);
- fieldAccessInfoCollection.extend(encodedField.field, info);
+ info = new FieldAccessInfoImpl(encodedField.getReference());
+ fieldAccessInfoCollection.extend(encodedField.getReference(), info);
}
// If `field` is an indirect reference, then create a mapping for it, such that we don't have
// to resolve the field the next time we see the reference.
- if (field != encodedField.field) {
+ if (field != encodedField.getReference()) {
fieldAccessInfoCollection.extend(field, info);
}
} else if (info == MISSING_FIELD_ACCESS_INFO) {
@@ -2122,7 +2122,7 @@
// targets another default method in the same interface (see testInvokeSpecialToDefault-
// Method). In a class, that would lead to a verification error.
if (encodedMethod.isNonPrivateVirtualMethod()
- && virtualMethodsTargetedByInvokeDirect.add(encodedMethod.method)) {
+ && virtualMethodsTargetedByInvokeDirect.add(encodedMethod.getReference())) {
workList.enqueueMarkMethodLiveAction(method, context, reason);
}
}
@@ -2442,7 +2442,7 @@
markVirtualMethodAsLive(
resolutionMethod,
graphReporter.reportReachableMethodAsLive(
- resolutionMethod.getDefinition().method, resolutionMethod));
+ resolutionMethod.getDefinition().getReference(), resolutionMethod));
return;
}
// Otherwise, we set the initial holder type to be the holder of the reachable method, which
@@ -2456,7 +2456,7 @@
lookup,
programMethod ->
graphReporter.reportReachableMethodAsLive(
- resolutionMethod.getDefinition().method, programMethod));
+ resolutionMethod.getDefinition().getReference(), programMethod));
}
}
@@ -2474,7 +2474,9 @@
// Note: It would be reasonable to not process methods already seen during the marking of
// program usages, but that would cause the methods to not be marked as library overrides.
markLibraryOrClasspathOverrideLive(
- instantiation, libraryClass, appInfo.resolveMethodOn(libraryClass, method.method));
+ instantiation,
+ libraryClass,
+ appInfo.resolveMethodOn(libraryClass, method.getReference()));
// Due to API conversion, some overrides can be hidden since they will be rewritten. See
// class comment of DesugaredLibraryAPIConverter and vivifiedType logic.
@@ -2482,11 +2484,12 @@
// maintains the library override. In the second enqueuer phase, the signature has been
// desugared, and the second resolution maintains the the library override.
if (instantiation.isClass()
- && appView.rewritePrefix.hasRewrittenTypeInSignature(method.method.proto, appView)) {
+ && appView.rewritePrefix.hasRewrittenTypeInSignature(
+ method.getReference().proto, appView)) {
DexMethod methodToResolve =
DesugaredLibraryAPIConverter.methodWithVivifiedTypeInSignature(
- method.method, method.getHolderType(), appView);
- assert methodToResolve != method.method;
+ method.getReference(), method.getHolderType(), appView);
+ assert methodToResolve != method.getReference();
markLibraryOrClasspathOverrideLive(
instantiation,
libraryClass,
@@ -2514,7 +2517,7 @@
if (instantiation.isClass()) {
// TODO(b/149976493): We need to mark these for lambdas too!
markOverridesAsLibraryMethodOverrides(
- instantiation.asClass(), lookup.asMethodTarget().getDefinition().method);
+ instantiation.asClass(), lookup.asMethodTarget().getDefinition().getReference());
}
}
@@ -2688,7 +2691,7 @@
}
public boolean isFieldReferenced(DexEncodedField field) {
- FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.field);
+ FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.getReference());
return info != null;
}
@@ -2834,7 +2837,7 @@
target,
programMethod ->
graphReporter.reportReachableMethodAsLive(
- resolvedMethod.method, programMethod)));
+ resolvedMethod.getReference(), programMethod)));
}
private void markVirtualDispatchTargetAsLive(
@@ -2874,7 +2877,7 @@
method -> {
DexProgramClass clazz = getProgramClassOrNull(method.getHolderType(), context);
if (clazz != null) {
- failedMethodResolutionTargets.add(method.method);
+ failedMethodResolutionTargets.add(method.getReference());
markMethodAsTargeted(new ProgramMethod(clazz, method), reason);
}
});
@@ -2920,7 +2923,7 @@
// If invoke target is invalid (inaccessible or not an instance-method) record it and stop.
DexClassAndMethod target = resolution.lookupInvokeSuperTarget(from.getHolder(), appInfo);
if (target == null) {
- failedMethodResolutionTargets.add(resolution.getResolvedMethod().method);
+ failedMethodResolutionTargets.add(resolution.getResolvedMethod().getReference());
return;
}
@@ -2961,7 +2964,7 @@
MainDexInfo.Builder builder = appView.appInfo().getMainDexInfo().builder();
liveTypes.getItems().forEach(builder::addRoot);
if (mode.isInitialMainDexTracing()) {
- liveMethods.getItems().forEach(method -> builder.addRoot(method.method));
+ liveMethods.getItems().forEach(method -> builder.addRoot(method.getReference()));
} else {
assert appView.appInfo().getMainDexInfo().isTracedMethodRootsCleared()
|| mode.isGenerateMainDexList();
@@ -3115,7 +3118,7 @@
}
void addLiveMethod(ProgramMethod method) {
- DexMethod signature = method.getDefinition().method;
+ DexMethod signature = method.getDefinition().getReference();
assert !liveMethods.containsKey(signature);
liveMethods.put(signature, method);
}
@@ -3399,7 +3402,7 @@
: "Expected type to be in live non-program types: " + clazz;
for (DexEncodedField field : clazz.fields()) {
if (clazz.isNotProgramClass() || isFieldReferenced(field)) {
- assert verifyReferencedType(field.field.type, worklist, app);
+ assert verifyReferencedType(field.getReference().type, worklist, app);
}
}
for (DexEncodedMethod method : clazz.methods()) {
@@ -3412,8 +3415,8 @@
private boolean verifyReferencedMethod(
DexEncodedMethod method, WorkList<DexClass> worklist, DexApplication app) {
- assert verifyReferencedType(method.method.proto.returnType, worklist, app);
- for (DexType param : method.method.proto.parameters.values) {
+ assert verifyReferencedType(method.getReference().proto.returnType, worklist, app);
+ for (DexType param : method.getReference().proto.parameters.values) {
assert verifyReferencedType(param, worklist, app);
}
return true;
@@ -3644,16 +3647,19 @@
return;
}
if (methodToKeep != singleTarget
- && !syntheticInterfaceMethodBridges.containsKey(methodToKeep.getDefinition().method)) {
- syntheticInterfaceMethodBridges.put(methodToKeep.getDefinition().method, methodToKeep);
- assert null == methodToKeep.getHolder().lookupMethod(methodToKeep.getDefinition().method);
+ && !syntheticInterfaceMethodBridges.containsKey(
+ methodToKeep.getDefinition().getReference())) {
+ syntheticInterfaceMethodBridges.put(
+ methodToKeep.getDefinition().getReference(), methodToKeep);
+ assert null
+ == methodToKeep.getHolder().lookupMethod(methodToKeep.getDefinition().getReference());
if (singleTargetMethod.isLibraryMethodOverride().isTrue()) {
methodToKeep.getDefinition().setLibraryMethodOverride(OptionalBool.TRUE);
}
DexProgramClass singleTargetHolder = singleTarget.getHolder();
assert singleTargetHolder.isInterface();
markVirtualMethodAsReachable(
- singleTargetMethod.method,
+ singleTargetMethod.getReference(),
singleTargetHolder.isInterface(),
singleTarget,
graphReporter.fakeReportShouldNotBeUsed());
@@ -3748,7 +3754,7 @@
DexProgramClass current = worklist.removeFirst();
assert visited.contains(current);
- if (current.lookupVirtualMethod(method.method) != null) {
+ if (current.lookupVirtualMethod(method.getReference()) != null) {
continue;
}
@@ -4482,7 +4488,7 @@
DexEncodedMethod target = holder.lookupDirectMethod(method);
if (target != null) {
// There is no dispatch on annotations, so only keep what is directly referenced.
- if (target.method == method) {
+ if (target.getReference() == method) {
markDirectStaticOrConstructorMethodAsLive(
new ProgramMethod(holder, target),
KeepReason.referencedInAnnotation(annotationHolder));
@@ -4490,7 +4496,7 @@
} else {
target = holder.lookupVirtualMethod(method);
// There is no dispatch on annotations, so only keep what is directly referenced.
- if (target != null && target.method == method) {
+ if (target != null && target.getReference() == method) {
markMethodAsTargeted(
new ProgramMethod(holder, target),
KeepReason.referencedInAnnotation(annotationHolder));
diff --git a/src/main/java/com/android/tools/r8/shaking/GraphReporter.java b/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
index 6459b7f..ac0d153 100644
--- a/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
+++ b/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
@@ -136,7 +136,7 @@
}
KeepRuleGraphNode ruleNode = getKeepRuleGraphNode(precondition, rule);
EdgeKind edgeKind = reportPrecondition(ruleNode);
- return reportEdge(ruleNode, getMethodGraphNode(method.method), edgeKind);
+ return reportEdge(ruleNode, getMethodGraphNode(method.getReference()), edgeKind);
}
KeepReasonWitness reportKeepMethod(
@@ -157,7 +157,7 @@
}
KeepRuleGraphNode ruleNode = getKeepRuleGraphNode(precondition, rule);
EdgeKind edgeKind = reportPrecondition(ruleNode);
- return reportEdge(ruleNode, getFieldGraphNode(field.field), edgeKind);
+ return reportEdge(ruleNode, getFieldGraphNode(field.getReference()), edgeKind);
}
KeepReasonWitness reportKeepField(
@@ -259,10 +259,11 @@
public KeepReasonWitness reportReachableMethodAsLive(
DexMethod overriddenMethod, ProgramMethod derivedMethod) {
- if (keptGraphConsumer != null && overriddenMethod != derivedMethod.getDefinition().method) {
+ if (keptGraphConsumer != null
+ && overriddenMethod != derivedMethod.getDefinition().getReference()) {
return reportEdge(
getMethodGraphNode(overriddenMethod),
- getMethodGraphNode(derivedMethod.getDefinition().method),
+ getMethodGraphNode(derivedMethod.getDefinition().getReference()),
EdgeKind.OverridingMethod);
}
return KeepReasonWitness.INSTANCE;
@@ -276,7 +277,7 @@
if (keptGraphConsumer != null && instantiation.isClass()) {
return reportEdge(
getClassGraphNode(instantiation.asClass().type),
- getMethodGraphNode(derivedMethod.getDefinition().method),
+ getMethodGraphNode(derivedMethod.getDefinition().getReference()),
EdgeKind.IsLibraryMethod);
}
return KeepReasonWitness.INSTANCE;
@@ -299,8 +300,8 @@
return KeepReasonWitness.INSTANCE;
}
return reportEdge(
- getMethodGraphNode(definition.method),
- getMethodGraphNode(implementation.method),
+ getMethodGraphNode(definition.getReference()),
+ getMethodGraphNode(implementation.getReference()),
EdgeKind.CompanionMethod);
}
@@ -375,14 +376,14 @@
// TODO(b/120959039): This should be dead code once no library classes are ever enqueued.
return KeepReasonWitness.INSTANCE;
}
- return registerEdge(getMethodGraphNode(method.method), reason);
+ return registerEdge(getMethodGraphNode(method.getReference()), reason);
}
public KeepReasonWitness registerField(DexEncodedField field, KeepReason reason) {
if (skipReporting(reason)) {
return KeepReasonWitness.INSTANCE;
}
- return registerEdge(getFieldGraphNode(field.field), reason);
+ return registerEdge(getFieldGraphNode(field.getReference()), reason);
}
private KeepReasonWitness registerEdge(GraphNode target, KeepReason reason) {
diff --git a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
index e843d0d..aa6844e 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
@@ -235,7 +235,7 @@
(enqueuer.isFieldLive(f)
|| enqueuer.isFieldReferenced(f)
|| f.getOptimizationInfo().valueHasBeenPropagated())
- && appView.graphLens().getOriginalFieldSignature(f.field).holder
+ && appView.graphLens().getOriginalFieldSignature(f.getReference()).holder
== sourceClass.type));
Iterables.addAll(
filteredMembers,
@@ -244,7 +244,7 @@
(enqueuer.isMethodLive(m)
|| enqueuer.isMethodTargeted(m)
|| m.getOptimizationInfo().returnValueHasBeenPropagated())
- && appView.graphLens().getOriginalMethodSignature(m.method).holder
+ && appView.graphLens().getOriginalMethodSignature(m.getReference()).holder
== sourceClass.type));
// If the number of member rules to hold is more than live members, we can't make it.
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
index 81239aa..7e9b166 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
@@ -307,13 +307,13 @@
@Override
public KeepMethodInfo getMethodInfo(DexEncodedMethod method, DexProgramClass holder) {
assert method.getHolderType() == holder.type;
- return keepMethodInfo.getOrDefault(method.method, KeepMethodInfo.bottom());
+ return keepMethodInfo.getOrDefault(method.getReference(), KeepMethodInfo.bottom());
}
@Override
public KeepFieldInfo getFieldInfo(DexEncodedField field, DexProgramClass holder) {
assert field.getHolderType() == holder.type;
- return keepFieldInfo.getOrDefault(field.field, KeepFieldInfo.bottom());
+ return keepFieldInfo.getOrDefault(field.getReference(), KeepFieldInfo.bottom());
}
public void joinClass(DexProgramClass clazz, Consumer<KeepClassInfo.Joiner> fn) {
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepReason.java b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
index 53b944f..5e6b3fd 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepReason.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
@@ -96,12 +96,12 @@
abstract String getKind();
public DexMethod getMethod() {
- return method.method;
+ return method.getReference();
}
@Override
public GraphNode getSourceNode(GraphReporter graphReporter) {
- return graphReporter.getMethodGraphNode(method.method);
+ return graphReporter.getMethodGraphNode(method.getReference());
}
}
@@ -264,10 +264,10 @@
if (holder.isDexClass()) {
return graphReporter.getClassGraphNode(holder.asDexClass().type);
} else if (holder.isDexEncodedField()) {
- return graphReporter.getFieldGraphNode(holder.asDexEncodedField().field);
+ return graphReporter.getFieldGraphNode(holder.asDexEncodedField().getReference());
} else {
assert holder.isDexEncodedMethod();
- return graphReporter.getMethodGraphNode(holder.asDexEncodedMethod().method);
+ return graphReporter.getMethodGraphNode(holder.asDexEncodedMethod().getReference());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
index 7760062..ab19637 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
@@ -53,7 +53,7 @@
clazz.annotations(), appInfo.dexItemFactory())) {
traceAnnotationsDirectDependencies(clazz.annotations());
}
- clazz.forEachField(field -> consumer.accept(field.field.type));
+ clazz.forEachField(field -> consumer.accept(field.getReference().type));
clazz.forEachProgramMethodMatching(
definition -> {
traceMethodDirectDependencies(definition.getReference(), consumer);
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
index afb39bf..525417c 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -105,7 +105,7 @@
// Browse annotation values types in search for enum.
// Each annotation value is represented by a virtual method.
for (DexEncodedMethod method : clazz.virtualMethods()) {
- DexProto proto = method.method.proto;
+ DexProto proto = method.getReference().proto;
if (proto.parameters.isEmpty()) {
DexType valueType = proto.returnType.toBaseType(appView.dexItemFactory());
if (valueType.isClassType()) {
@@ -143,7 +143,7 @@
addDirectDependency(clazz);
// Add enum classes used for values as direct dependencies.
for (DexEncodedMethod method : clazz.virtualMethods()) {
- DexProto proto = method.method.proto;
+ DexProto proto = method.getReference().proto;
if (proto.parameters.isEmpty()) {
DexType valueType = proto.returnType.toBaseType(appView.dexItemFactory());
if (isEnum(valueType)) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
index c6afc11..8c0d0b4 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
@@ -75,11 +75,13 @@
memberRuleBuilder.setRuleType(ProguardMemberType.METHOD);
memberRuleBuilder.getAccessFlags().setFlags(method.accessFlags);
memberRuleBuilder.setName(
- IdentifierPatternWithWildcards.withoutWildcards(method.method.name.toString()));
- memberRuleBuilder.setTypeMatcher(ProguardTypeMatcher.create(method.method.proto.returnType));
- List<ProguardTypeMatcher> arguments = Arrays.stream(method.method.proto.parameters.values)
- .map(ProguardTypeMatcher::create)
- .collect(Collectors.toList());
+ IdentifierPatternWithWildcards.withoutWildcards(method.getReference().name.toString()));
+ memberRuleBuilder.setTypeMatcher(
+ ProguardTypeMatcher.create(method.getReference().proto.returnType));
+ List<ProguardTypeMatcher> arguments =
+ Arrays.stream(method.getReference().proto.parameters.values)
+ .map(ProguardTypeMatcher::create)
+ .collect(Collectors.toList());
memberRuleBuilder.setArguments(arguments);
builder.getMemberRules().add(memberRuleBuilder.build());
return builder.build();
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
index 1b80a1e..2aba15e 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
@@ -185,7 +185,8 @@
AppView<?> appView,
Consumer<AnnotationMatchResult> matchedAnnotationsConsumer,
DexStringCache stringCache) {
- DexField originalSignature = appView.graphLens().getOriginalFieldSignature(field.field);
+ DexField originalSignature =
+ appView.graphLens().getOriginalFieldSignature(field.getReference());
switch (getRuleType()) {
case ALL:
case ALL_FIELDS:
@@ -236,7 +237,8 @@
AppView<?> appView,
Consumer<AnnotationMatchResult> matchedAnnotationsConsumer,
DexStringCache stringCache) {
- DexMethod originalSignature = appView.graphLens().getOriginalMethodSignature(method.method);
+ DexMethod originalSignature =
+ appView.graphLens().getOriginalMethodSignature(method.getReference());
switch (getRuleType()) {
case ALL_METHODS:
if (method.isClassInitializer()) {
@@ -415,7 +417,7 @@
case INIT: {
result.append(getName());
result.append('(');
- result.append(StringUtils.join(getArguments(), ","));
+ result.append(StringUtils.join(",", getArguments()));
result.append(')');
break;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index 8848ece..e78f53b 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -387,8 +387,8 @@
assert !encodedMethod.shouldNotHaveCode();
continue;
}
- propagateAssumeRules(clazz.type, encodedMethod.method, subTypes, noSideEffects);
- propagateAssumeRules(clazz.type, encodedMethod.method, subTypes, assumedValues);
+ propagateAssumeRules(clazz.type, encodedMethod.getReference(), subTypes, noSideEffects);
+ propagateAssumeRules(clazz.type, encodedMethod.getReference(), subTypes, assumedValues);
}
}
@@ -414,7 +414,7 @@
if (target == null || target.getHolderType() == type) {
continue;
}
- ProguardMemberRule ruleInSubType = assumeRulePool.get(target.method);
+ ProguardMemberRule ruleInSubType = assumeRulePool.get(target.getReference());
// We are looking for the greatest lower bound of assume rules from all sub types.
// If any subtype doesn't have a matching assume rule, the lower bound is literally nothing.
if (ruleInSubType == null) {
@@ -578,7 +578,7 @@
}
for (DexEncodedMethod method : clazz.virtualMethods()) {
// Check if we already added this.
- Wrapper<DexMethod> wrapped = MethodSignatureEquivalence.get().wrap(method.method);
+ Wrapper<DexMethod> wrapped = MethodSignatureEquivalence.get().wrap(method.getReference());
if (!seenMethods.add(wrapped)) {
continue;
}
@@ -592,7 +592,10 @@
private void tryAndKeepMethodOnClass(DexEncodedMethod method, ProguardMemberRule rule) {
SingleResolutionResult resolutionResult =
- appView.appInfo().resolveMethodOn(originalClazz, method.method).asSingleResolution();
+ appView
+ .appInfo()
+ .resolveMethodOn(originalClazz, method.getReference())
+ .asSingleResolution();
if (resolutionResult == null || !resolutionResult.isVirtualTarget()) {
return;
}
@@ -1008,7 +1011,7 @@
DexDefinition precondition,
ProguardIfRule ifRule) {
if (methodsMarked != null
- && methodsMarked.contains(MethodSignatureEquivalence.get().wrap(method.method))) {
+ && methodsMarked.contains(MethodSignatureEquivalence.get().wrap(method.getReference()))) {
// Ignore, method is overridden in sub class.
return;
}
@@ -1019,7 +1022,7 @@
getClass(), "Marking method `%s` due to `%s { %s }`.", method, context, rule);
}
if (methodsMarked != null) {
- methodsMarked.add(MethodSignatureEquivalence.get().wrap(method.method));
+ methodsMarked.add(MethodSignatureEquivalence.get().wrap(method.getReference()));
}
addItemToSets(method, context, rule, precondition, ifRule);
}
@@ -1075,13 +1078,13 @@
private void includeDescriptorClasses(DexDefinition item, ProguardKeepRuleBase context) {
if (item.isDexEncodedMethod()) {
- DexMethod method = item.asDexEncodedMethod().method;
+ DexMethod method = item.asDexEncodedMethod().getReference();
includeDescriptor(item, method.proto.returnType, context);
for (DexType value : method.proto.parameters.values) {
includeDescriptor(item, value, context);
}
} else if (item.isDexEncodedField()) {
- DexField field = item.asDexEncodedField().field;
+ DexField field = item.asDexEncodedField().getReference();
includeDescriptor(item, field.type, context);
} else {
assert item.isDexClass();
@@ -1114,7 +1117,7 @@
return;
}
if (options.isGeneratingDex()
- && encodedMethod.method.isLambdaDeserializeMethod(appView.dexItemFactory())) {
+ && encodedMethod.getReference().isLambdaDeserializeMethod(appView.dexItemFactory())) {
// Don't keep lambda deserialization methods.
return;
}
@@ -1131,7 +1134,7 @@
"The rule `"
+ rule
+ "` is ignored because the targeting interface method `"
- + encodedMethod.method.toSourceString()
+ + encodedMethod.getReference().toSourceString()
+ "` will be desugared."));
}
return;
@@ -1244,7 +1247,7 @@
if (!item.isDexEncodedMethod()) {
throw new Unreachable();
}
- whyAreYouNotInlining.add(item.asDexEncodedMethod().method);
+ whyAreYouNotInlining.add(item.asDexEncodedMethod().getReference());
context.markAsUsed();
} else if (context.isClassInlineRule()) {
ClassInlineRule classInlineRule = context.asClassInlineRule();
@@ -1285,13 +1288,13 @@
if (item.isDexEncodedField()) {
DexEncodedField field = item.asDexEncodedField();
if (field.isProgramField(appView)) {
- neverPropagateValue.add(item.asDexEncodedField().field);
+ neverPropagateValue.add(item.asDexEncodedField().getReference());
context.markAsUsed();
}
} else if (item.isDexEncodedMethod()) {
DexEncodedMethod method = item.asDexEncodedMethod();
if (method.isProgramMethod(appView)) {
- neverPropagateValue.add(item.asDexEncodedMethod().method);
+ neverPropagateValue.add(item.asDexEncodedMethod().getReference());
context.markAsUsed();
}
}
@@ -1301,15 +1304,15 @@
}
} else if (context instanceof ProguardIdentifierNameStringRule) {
if (item.isDexEncodedField()) {
- identifierNameStrings.add(item.asDexEncodedField().field);
+ identifierNameStrings.add(item.asDexEncodedField().getReference());
context.markAsUsed();
} else if (item.isDexEncodedMethod()) {
- identifierNameStrings.add(item.asDexEncodedMethod().method);
+ identifierNameStrings.add(item.asDexEncodedMethod().getReference());
context.markAsUsed();
}
} else if (context instanceof ConstantArgumentRule) {
if (item.isDexEncodedMethod()) {
- keepParametersWithConstantValue.add(item.asDexEncodedMethod().method);
+ keepParametersWithConstantValue.add(item.asDexEncodedMethod().getReference());
context.markAsUsed();
}
} else if (context instanceof ReprocessClassInitializerRule) {
@@ -1317,10 +1320,10 @@
if (clazz != null && clazz.hasClassInitializer()) {
switch (context.asReprocessClassInitializerRule().getType()) {
case ALWAYS:
- reprocess.add(clazz.getClassInitializer().method);
+ reprocess.add(clazz.getClassInitializer().getReference());
break;
case NEVER:
- neverReprocess.add(clazz.getClassInitializer().method);
+ neverReprocess.add(clazz.getClassInitializer().getReference());
break;
default:
throw new Unreachable();
@@ -1332,10 +1335,10 @@
DexEncodedMethod method = item.asDexEncodedMethod();
switch (context.asReprocessMethodRule().getType()) {
case ALWAYS:
- reprocess.add(method.method);
+ reprocess.add(method.getReference());
break;
case NEVER:
- neverReprocess.add(method.method);
+ neverReprocess.add(method.getReference());
break;
default:
throw new Unreachable();
@@ -1344,7 +1347,7 @@
}
} else if (context instanceof UnusedArgumentRule) {
if (item.isDexEncodedMethod()) {
- keepUnusedArguments.add(item.asDexEncodedMethod().method);
+ keepUnusedArguments.add(item.asDexEncodedMethod().getReference());
context.markAsUsed();
}
} else {
diff --git a/src/main/java/com/android/tools/r8/shaking/ScopedDexMethodSet.java b/src/main/java/com/android/tools/r8/shaking/ScopedDexMethodSet.java
index d3b7e21..07ad580 100644
--- a/src/main/java/com/android/tools/r8/shaking/ScopedDexMethodSet.java
+++ b/src/main/java/com/android/tools/r8/shaking/ScopedDexMethodSet.java
@@ -46,7 +46,7 @@
}
public boolean addMethod(DexEncodedMethod method) {
- Wrapper<DexMethod> wrapped = METHOD_EQUIVALENCE.wrap(method.method);
+ Wrapper<DexMethod> wrapped = METHOD_EQUIVALENCE.wrap(method.getReference());
if (contains(wrapped)) {
return false;
}
@@ -55,7 +55,7 @@
}
public AddMethodIfMoreVisibleResult addMethodIfMoreVisible(DexEncodedMethod method) {
- Wrapper<DexMethod> wrapped = METHOD_EQUIVALENCE.wrap(method.method);
+ Wrapper<DexMethod> wrapped = METHOD_EQUIVALENCE.wrap(method.getReference());
DexEncodedMethod existing = lookup(wrapped);
if (existing == null) {
items.put(wrapped, method);
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index 9b7a66b..6974a61 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -276,7 +276,7 @@
AppInfoWithLiveness appInfo = appView.appInfo();
InternalOptions options = appView.options();
int firstUnreachable =
- firstUnreachableIndex(methods, method -> appInfo.isLiveMethod(method.method));
+ firstUnreachableIndex(methods, method -> appInfo.isLiveMethod(method.getReference()));
// Return the original array if all methods are used.
if (firstUnreachable == -1) {
return null;
@@ -295,7 +295,7 @@
method.shouldNotHaveCode() && !method.hasCode()
? method
: method.toMethodThatLogsError(appView));
- methodsToKeepForConfigurationDebugging.add(method.method);
+ methodsToKeepForConfigurationDebugging.add(method.getReference());
} else if (appInfo.isTargetedMethod(method.getReference())) {
// If the method is already abstract, and doesn't have code, let it be.
if (method.shouldNotHaveCode() && !method.hasCode()) {
@@ -303,7 +303,7 @@
continue;
}
if (Log.ENABLED) {
- Log.debug(getClass(), "Making method %s abstract.", method.method);
+ Log.debug(getClass(), "Making method %s abstract.", method.getReference());
}
// Final classes cannot be abstract, so we have to keep the method in that case.
// Also some other kinds of methods cannot be abstract, so keep them around.
@@ -315,7 +315,7 @@
&& !method.isSynchronized()
&& !method.accessFlags.isPrivate()
&& !method.isStatic()
- && !appInfo.isFailedResolutionTarget(method.method);
+ && !appInfo.isFailedResolutionTarget(method.getReference());
// Private methods and static methods can only be targeted yet non-live as the result of
// an invalid invoke. They will not actually be called at runtime but we have to keep them
// as non-abstract (see above) to produce the same failure mode.
@@ -323,7 +323,7 @@
allowAbstract ? method.toAbstractMethod() : method.toEmptyThrowingMethod(options));
} else {
if (Log.ENABLED) {
- Log.debug(getClass(), "Removing method %s.", method.method);
+ Log.debug(getClass(), "Removing method %s.", method.getReference());
}
unusedItemsPrinter.registerUnusedMethod(method);
}
@@ -356,7 +356,7 @@
reachableOrReferencedFields.add(field);
} else {
if (Log.ENABLED) {
- Log.debug(getClass(), "Removing field %s.", field.field);
+ Log.debug(getClass(), "Removing field %s.", field.getReference());
}
unusedItemsPrinter.registerUnusedField(field);
}
@@ -379,7 +379,7 @@
// Pinned field which type is never instantiated are always null, they are marked as dead
// so their reads and writes are cleared, but they are still in the program.
assert !field.getOptimizationInfo().isDead() || appView.appInfo().isPinned(field)
- : "Expected field `" + field.field.toSourceString() + "` to be absent";
+ : "Expected field `" + field.getReference().toSourceString() + "` to be absent";
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/UnusedItemsPrinter.java b/src/main/java/com/android/tools/r8/shaking/UnusedItemsPrinter.java
index 5b89abf..6bd61cd 100644
--- a/src/main/java/com/android/tools/r8/shaking/UnusedItemsPrinter.java
+++ b/src/main/java/com/android/tools/r8/shaking/UnusedItemsPrinter.java
@@ -105,15 +105,15 @@
append(accessFlags);
append(" ");
}
- append(method.method.proto.returnType.toSourceString());
+ append(method.getReference().proto.returnType.toSourceString());
append(" ");
- append(method.method.name.toSourceString());
+ append(method.getReference().name.toSourceString());
append("(");
- for (int i = 0; i < method.method.proto.parameters.values.length; i++) {
+ for (int i = 0; i < method.getReference().proto.parameters.values.length; i++) {
if (i != 0) {
append(",");
}
- append(method.method.proto.parameters.values[i].toSourceString());
+ append(method.getReference().proto.parameters.values[i].toSourceString());
}
append(")");
newline();
@@ -126,9 +126,9 @@
append(accessFlags);
append(" ");
}
- append(field.field.type.toSourceString());
+ append(field.getReference().type.toSourceString());
append(" ");
- append(field.field.name.toSourceString());
+ append(field.getReference().name.toSourceString());
newline();
}
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 761b314..3475116 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -208,7 +208,7 @@
// Map from source class to target class.
private final MutableBidirectionalManyToOneMap<DexType, DexType> mergedClasses =
- new BidirectionalManyToOneHashMap<>();
+ BidirectionalManyToOneHashMap.newIdentityHashMap();
// Set of types that must not be merged into their subtype.
private final Set<DexType> pinnedTypes = Sets.newIdentityHashSet();
@@ -512,7 +512,7 @@
}
// Check if the target is overriding and narrowing the access.
if (method.isPublic()) {
- DexEncodedMethod targetOverride = target.lookupVirtualMethod(method.method);
+ DexEncodedMethod targetOverride = target.lookupVirtualMethod(method.getReference());
if (targetOverride != null && !targetOverride.isPublic()) {
return true;
}
@@ -565,7 +565,7 @@
Set<Wrapper<DexMethod>> filteredSignatures = new HashSet<>();
for (DexProgramClass clazz : appInfo.classes()) {
for (DexEncodedMethod encodedMethod : clazz.methods()) {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
DexClass definition = appInfo.definitionFor(method.holder);
if (definition != null
&& definition.isProgramClass()
@@ -695,7 +695,7 @@
for (DexProgramClass clazz : appInfo.classes()) {
for (DexEncodedMethod encodedMethod : clazz.methods()) {
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
DexMethod originalMethod = graphLens.getOriginalMethodSignature(method);
DexMethod renamedMethod = graphLens.getRenamedMethodSignature(originalMethod);
@@ -727,7 +727,8 @@
private boolean methodResolutionMayChange(DexProgramClass source, DexProgramClass target) {
for (DexEncodedMethod virtualSourceMethod : source.virtualMethods()) {
- DexEncodedMethod directTargetMethod = target.lookupDirectMethod(virtualSourceMethod.method);
+ DexEncodedMethod directTargetMethod =
+ target.lookupDirectMethod(virtualSourceMethod.getReference());
if (directTargetMethod != null) {
// A private method shadows a virtual method. This situation is rare, since it is not
// allowed by javac. Therefore, we just give up in this case. (In principle, it would be
@@ -763,7 +764,7 @@
// Conservatively find all possible targets for this method.
LookupResultSuccess lookupResult =
appInfo
- .resolveMethodOnInterface(method.getHolderType(), method.method)
+ .resolveMethodOnInterface(method.getHolderType(), method.getReference())
.lookupVirtualDispatchTargets(target, appInfo)
.asLookupResultSuccess();
assert lookupResult != null;
@@ -873,11 +874,12 @@
for (DexType interfaceType : target.interfaces.values) {
DexClass clazz = appInfo.definitionFor(interfaceType);
for (DexEncodedField staticField : clazz.staticFields()) {
- staticFieldsInInterfacesOfTarget.add(equivalence.wrap(staticField.field));
+ staticFieldsInInterfacesOfTarget.add(equivalence.wrap(staticField.getReference()));
}
}
for (DexEncodedField instanceField : source.instanceFields()) {
- if (staticFieldsInInterfacesOfTarget.contains(equivalence.wrap(instanceField.field))) {
+ if (staticFieldsInInterfacesOfTarget.contains(
+ equivalence.wrap(instanceField.getReference()))) {
// An instruction "iget Target.f" or "iput Target.f" that used to hit a static field in an
// interface would now hit an instance field from [source], so that an IncompatibleClass-
// ChangeError would no longer be thrown. Abort merge.
@@ -926,7 +928,7 @@
DexEncodedMethod resultingConstructor =
renameConstructor(directMethod, availableMethodSignatures);
add(directMethods, resultingConstructor, MethodSignatureEquivalence.get());
- blockRedirectionOfSuperCalls(resultingConstructor.method);
+ blockRedirectionOfSuperCalls(resultingConstructor.getReference());
} else {
DexEncodedMethod resultingDirectMethod =
renameMethod(
@@ -934,9 +936,10 @@
availableMethodSignatures,
directMethod.isClassInitializer() ? Rename.NEVER : Rename.IF_NEEDED);
add(directMethods, resultingDirectMethod, MethodSignatureEquivalence.get());
- deferredRenamings.map(directMethod.method, resultingDirectMethod.method);
- deferredRenamings.recordMove(directMethod.method, resultingDirectMethod.method);
- blockRedirectionOfSuperCalls(resultingDirectMethod.method);
+ deferredRenamings.map(directMethod.getReference(), resultingDirectMethod.getReference());
+ deferredRenamings.recordMove(
+ directMethod.getReference(), resultingDirectMethod.getReference());
+ blockRedirectionOfSuperCalls(resultingDirectMethod.getReference());
}
}
@@ -945,7 +948,7 @@
if (shadowedBy != null) {
if (virtualMethod.isAbstract()) {
// Remove abstract/interface methods that are shadowed.
- deferredRenamings.map(virtualMethod.method, shadowedBy.method);
+ deferredRenamings.map(virtualMethod.getReference(), shadowedBy.getReference());
// The override now corresponds to the method in the parent, so unset its synthetic flag
// if the method in the parent is not synthetic.
@@ -977,8 +980,10 @@
renameMethod(virtualMethod, availableMethodSignatures, Rename.NEVER);
resultingVirtualMethod.setLibraryMethodOverride(
virtualMethod.isLibraryMethodOverride());
- deferredRenamings.map(virtualMethod.method, resultingVirtualMethod.method);
- deferredRenamings.recordMove(virtualMethod.method, resultingVirtualMethod.method);
+ deferredRenamings.map(
+ virtualMethod.getReference(), resultingVirtualMethod.getReference());
+ deferredRenamings.recordMove(
+ virtualMethod.getReference(), resultingVirtualMethod.getReference());
add(virtualMethods, resultingVirtualMethod, MethodSignatureEquivalence.get());
continue;
}
@@ -1005,7 +1010,7 @@
makeStatic(resultingDirectMethod);
// Update method pool collection now that we are adding a new public method.
- methodPoolForTarget.seen(resultingDirectMethod.method);
+ methodPoolForTarget.seen(resultingDirectMethod.getReference());
} else {
// This virtual method could be called directly from a sub class via an invoke-super in-
// struction. Therefore, we translate this virtual method into a direct method, such that
@@ -1019,8 +1024,9 @@
// Record that invoke-super instructions in the target class should be redirected to the
// newly created direct method.
- redirectSuperCallsInTarget(virtualMethod.method, resultingDirectMethod.method);
- blockRedirectionOfSuperCalls(resultingDirectMethod.method);
+ redirectSuperCallsInTarget(
+ virtualMethod.getReference(), resultingDirectMethod.getReference());
+ blockRedirectionOfSuperCalls(resultingDirectMethod.getReference());
if (shadowedBy == null) {
// In addition to the newly added direct method, create a virtual method such that we do
@@ -1029,12 +1035,14 @@
// it turns out that the method is never used, it will be removed by the final round
// of tree shaking.
shadowedBy = buildBridgeMethod(virtualMethod, resultingDirectMethod);
- deferredRenamings.recordCreationOfBridgeMethod(virtualMethod.method, shadowedBy.method);
+ deferredRenamings.recordCreationOfBridgeMethod(
+ virtualMethod.getReference(), shadowedBy.getReference());
add(virtualMethods, shadowedBy, MethodSignatureEquivalence.get());
}
- deferredRenamings.map(virtualMethod.method, shadowedBy.method);
- deferredRenamings.recordMove(virtualMethod.method, resultingDirectMethod.method);
+ deferredRenamings.map(virtualMethod.getReference(), shadowedBy.getReference());
+ deferredRenamings.recordMove(
+ virtualMethod.getReference(), resultingDirectMethod.getReference());
}
if (abortMerge) {
@@ -1046,7 +1054,7 @@
// Step 2: Merge fields
Set<DexString> existingFieldNames = new HashSet<>();
for (DexEncodedField field : target.fields()) {
- existingFieldNames.add(field.field.name);
+ existingFieldNames.add(field.getReference().name);
}
// In principle, we could allow multiple fields with the same name, and then only rename the
@@ -1223,8 +1231,8 @@
private DexEncodedMethod buildBridgeMethod(
DexEncodedMethod method, DexEncodedMethod invocationTarget) {
DexType holder = target.type;
- DexProto proto = method.method.proto;
- DexString name = method.method.name;
+ DexProto proto = method.getReference().proto;
+ DexString name = method.getReference().name;
DexMethod newMethod = application.dexItemFactory.createMethod(holder, proto, name);
MethodAccessFlags accessFlags = method.accessFlags.copy();
accessFlags.setBridge();
@@ -1235,8 +1243,8 @@
SynthesizedBridgeCode code =
new SynthesizedBridgeCode(
newMethod,
- appView.graphLens().getOriginalMethodSignature(method.method),
- invocationTarget.method,
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ invocationTarget.getReference(),
invocationTarget.isPrivateMethod() ? DIRECT : STATIC,
target.isInterface());
@@ -1265,7 +1273,7 @@
// Returns the method that shadows the given method, or null if method is not shadowed.
private DexEncodedMethod findMethodInTarget(DexEncodedMethod method) {
- ResolutionResult resolutionResult = appInfo.resolveMethodOn(target, method.method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(target, method.getReference());
if (!resolutionResult.isSingleResolution()) {
// May happen in case of missing classes, or if multiple implementations were found.
abortMerge = true;
@@ -1285,7 +1293,7 @@
"The non-abstract type `"
+ target.type.toSourceString()
+ "` does not implement the method `"
- + method.method.toSourceString()
+ + method.getReference().toSourceString()
+ "`.");
}
}
@@ -1321,8 +1329,8 @@
int i = 0;
for (DexEncodedField field : sourceFields) {
DexEncodedField resultingField = renameFieldIfNeeded(field, availableFieldSignatures);
- existingFieldNames.add(resultingField.field.name);
- deferredRenamings.map(field.field, resultingField.field);
+ existingFieldNames.add(resultingField.getReference().name);
+ deferredRenamings.map(field.getReference(), resultingField.getReference());
result[i] = resultingField;
i++;
}
@@ -1354,14 +1362,15 @@
do {
DexString newName = getFreshName(TEMPORARY_INSTANCE_INITIALIZER_PREFIX, count, oldHolder);
newSignature =
- application.dexItemFactory.createMethod(target.type, method.method.proto, newName);
+ application.dexItemFactory.createMethod(
+ target.type, method.getReference().proto, newName);
count++;
} while (!availableMethodSignatures.test(newSignature));
DexEncodedMethod result = method.toTypeSubstitutedMethod(newSignature);
result.getMutableOptimizationInfo().markForceInline();
- deferredRenamings.map(method.method, result.method);
- deferredRenamings.recordMove(method.method, result.method);
+ deferredRenamings.map(method.getReference(), result.getReference());
+ deferredRenamings.recordMove(method.getReference(), result.getReference());
// Renamed constructors turn into ordinary private functions. They can be private, as
// they are only references from their direct subclass, which they were merged into.
result.accessFlags.unsetConstructor();
@@ -1371,7 +1380,7 @@
private DexEncodedMethod renameMethod(
DexEncodedMethod method, Predicate<DexMethod> availableMethodSignatures, Rename strategy) {
- return renameMethod(method, availableMethodSignatures, strategy, method.method.proto);
+ return renameMethod(method, availableMethodSignatures, strategy, method.getReference().proto);
}
private DexEncodedMethod renameMethod(
@@ -1382,7 +1391,7 @@
// We cannot handle renaming static initializers yet and constructors should have been
// renamed already.
assert !method.accessFlags.isConstructor() || strategy == Rename.NEVER;
- DexString oldName = method.method.name;
+ DexString oldName = method.getReference().name;
DexType oldHolder = method.getHolderType();
DexMethod newSignature;
@@ -1417,17 +1426,18 @@
private DexEncodedField renameFieldIfNeeded(
DexEncodedField field, Predicate<DexField> availableFieldSignatures) {
- DexString oldName = field.field.name;
+ DexString oldName = field.getReference().name;
DexType oldHolder = field.getHolderType();
DexField newSignature =
- application.dexItemFactory.createField(target.type, field.field.type, oldName);
+ application.dexItemFactory.createField(target.type, field.getReference().type, oldName);
if (!availableFieldSignatures.test(newSignature)) {
int count = 1;
do {
DexString newName = getFreshName(oldName.toSourceString(), count, oldHolder);
newSignature =
- application.dexItemFactory.createField(target.type, field.field.type, newName);
+ application.dexItemFactory.createField(
+ target.type, field.getReference().type, newName);
count++;
} while (!availableFieldSignatures.test(newSignature));
}
@@ -1520,7 +1530,7 @@
@Override
public DexEncodedMethod recordMethodChange(
DexEncodedMethod method, DexEncodedMethod newMethod) {
- recordMethodChange(method.method, newMethod.method);
+ recordMethodChange(method.getReference(), newMethod.getReference());
if (newMethod.isNonPrivateVirtualMethod()) {
// Since we changed the return type or one of the parameters, this method cannot be a
// classpath or library method override, since we only class merge program classes.
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 008380c..467c168 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
@@ -11,8 +11,7 @@
import com.android.tools.r8.graph.DexProgramClass;
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.GraphLens.NestedGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.ir.code.Invoke.Type;
@@ -75,16 +74,9 @@
Set<DexMethod> mergedMethods,
Map<DexType, Map<DexMethod, GraphLensLookupResultProvider>>
contextualVirtualToDirectMethodMaps,
- BidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures,
- Map<DexMethod, DexMethod> originalMethodSignaturesForBridges,
- GraphLens previousLens) {
- super(
- mergedClasses.getForwardMap(),
- methodMap,
- fieldMap,
- originalMethodSignatures,
- previousLens,
- appView.dexItemFactory());
+ BidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures,
+ Map<DexMethod, DexMethod> originalMethodSignaturesForBridges) {
+ super(appView, fieldMap, methodMap, mergedClasses.getForwardMap(), newMethodSignatures);
this.appView = appView;
this.mergedClasses = mergedClasses;
this.contextualVirtualToDirectMethodMaps = contextualVirtualToDirectMethodMaps;
@@ -172,7 +164,7 @@
private final Map<DexType, Map<DexMethod, GraphLensLookupResultProvider>>
contextualVirtualToDirectMethodMaps = new IdentityHashMap<>();
- private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> originalMethodSignatures =
+ private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures =
new BidirectionalOneToOneHashMap<>();
private final Map<DexMethod, DexMethod> originalMethodSignaturesForBridges =
new IdentityHashMap<>();
@@ -216,8 +208,8 @@
context);
}
}
- builder.originalMethodSignatures.forEach(
- (renamedMethodSignature, originalMethodSignature) ->
+ builder.newMethodSignatures.forEach(
+ (originalMethodSignature, renamedMethodSignature) ->
newBuilder.recordMove(
originalMethodSignature,
builder.getMethodSignatureAfterClassMerging(
@@ -244,9 +236,8 @@
methodMap,
mergedMethodsBuilder.build(),
contextualVirtualToDirectMethodMaps,
- originalMethodSignatures,
- originalMethodSignaturesForBridges,
- appView.graphLens());
+ newMethodSignatures,
+ originalMethodSignaturesForBridges);
}
private DexField getFieldSignatureAfterClassMerging(
@@ -309,7 +300,7 @@
}
public boolean hasOriginalSignatureMappingFor(DexMethod method) {
- return originalMethodSignatures.containsKey(method)
+ return newMethodSignatures.containsValue(method)
|| originalMethodSignaturesForBridges.containsKey(method);
}
@@ -327,7 +318,7 @@
}
public void recordMove(DexMethod from, DexMethod to) {
- originalMethodSignatures.put(to, from);
+ newMethodSignatures.put(from, to);
}
public void recordCreationOfBridgeMethod(DexMethod from, DexMethod to) {
@@ -345,7 +336,7 @@
fieldMap.putAll(builder.fieldMap);
methodMap.putAll(builder.methodMap);
mergedMethodsBuilder.addAll(builder.mergedMethodsBuilder.build());
- originalMethodSignatures.putAll(builder.originalMethodSignatures);
+ newMethodSignatures.putAll(builder.newMethodSignatures);
originalMethodSignaturesForBridges.putAll(builder.originalMethodSignaturesForBridges);
for (DexType context : builder.contextualVirtualToDirectMethodMaps.keySet()) {
Map<DexMethod, GraphLensLookupResultProvider> current =
diff --git a/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java b/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
index d56e455..1099f62 100644
--- a/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
+++ b/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
@@ -211,8 +211,8 @@
+ '.'
+ method.getMethodName()
+ StringUtils.join(
- ListUtils.map(method.getFormalTypes(), TypeReference::getTypeName),
",",
+ ListUtils.map(method.getFormalTypes(), TypeReference::getTypeName),
BraceType.PARENS);
}
if (node instanceof FieldGraphNode) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index d610175..ed9d843 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -18,8 +18,8 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.TreeFixerBase;
import com.android.tools.r8.ir.code.NumberGenerator;
@@ -28,11 +28,9 @@
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.SetUtils;
-import com.android.tools.r8.utils.collections.BidirectionalManyToManyRepresentativeMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
-import com.android.tools.r8.utils.collections.BidirectionalOneToManyRepresentativeHashMap;
-import com.android.tools.r8.utils.collections.MutableBidirectionalOneToManyRepresentativeMap;
+import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
import com.android.tools.r8.utils.structural.RepresentativeMap;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
@@ -72,13 +70,11 @@
public static class SyntheticFinalizationGraphLens extends NestedGraphLens {
private SyntheticFinalizationGraphLens(
- GraphLens previous,
- Map<DexType, DexType> typeMap,
+ AppView<?> appView,
BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
- Map<DexMethod, DexMethod> methodMap,
- BidirectionalManyToManyRepresentativeMap<DexMethod, DexMethod> originalMethodSignatures,
- DexItemFactory factory) {
- super(typeMap, methodMap, fieldMap, originalMethodSignatures, previous, factory);
+ BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap,
+ Map<DexType, DexType> typeMap) {
+ super(appView, fieldMap, methodMap, typeMap);
}
@Override
@@ -89,13 +85,11 @@
private static class Builder {
- Map<DexType, DexType> typeMap = new IdentityHashMap<>();
- BidirectionalManyToOneRepresentativeHashMap<DexField, DexField> fieldMap =
- new BidirectionalManyToOneRepresentativeHashMap<>();
- Map<DexMethod, DexMethod> methodMap = new IdentityHashMap<>();
-
- protected final MutableBidirectionalOneToManyRepresentativeMap<DexMethod, DexMethod>
- originalMethodSignatures = new BidirectionalOneToManyRepresentativeHashMap<>();
+ private final BidirectionalManyToOneRepresentativeHashMap<DexField, DexField> fieldMap =
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
+ private final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap =
+ BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
+ private final Map<DexType, DexType> typeMap = new IdentityHashMap<>();
void move(DexType from, DexType to) {
DexType old = typeMap.put(from, to);
@@ -108,22 +102,14 @@
}
void move(DexMethod from, DexMethod to) {
- DexMethod old = methodMap.put(from, to);
- assert old == null || old == to;
- originalMethodSignatures.put(to, from);
+ methodMap.put(from, to);
}
- SyntheticFinalizationGraphLens build(GraphLens previous, DexItemFactory factory) {
+ SyntheticFinalizationGraphLens build(AppView<?> appView) {
if (typeMap.isEmpty() && fieldMap.isEmpty() && methodMap.isEmpty()) {
return null;
}
- return new SyntheticFinalizationGraphLens(
- previous,
- typeMap,
- fieldMap,
- methodMap,
- originalMethodSignatures,
- factory);
+ return new SyntheticFinalizationGraphLens(appView, fieldMap, methodMap, typeMap);
}
}
@@ -262,7 +248,7 @@
new CommittedSyntheticsCollection(
committed.getLegacyTypes(), finalMethods, finalClasses),
ImmutableList.of()),
- lensBuilder.build(appView.graphLens(), appView.dexItemFactory()),
+ lensBuilder.build(appView),
PrunedItems.builder().setPrunedApp(application).addRemovedClasses(prunedSynthetics).build(),
mainDexInfoBuilder.build());
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 7148738..cb1e91b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -31,6 +31,7 @@
HORIZONTAL_INIT_TYPE_ARGUMENT_2(SYNTHETIC_CLASS_SEPARATOR + "IA$2", false, true),
HORIZONTAL_INIT_TYPE_ARGUMENT_3(SYNTHETIC_CLASS_SEPARATOR + "IA$3", false, true),
// Method synthetics.
+ RECORD_HELPER("Record", true),
BACKPORT("Backport", true),
STATIC_INTERFACE_CALL("StaticInterfaceCall", true),
TO_STRING_IF_NOT_NULL("ToStringIfNotNull", true),
diff --git a/src/main/java/com/android/tools/r8/tracereferences/KeepRuleFormatter.java b/src/main/java/com/android/tools/r8/tracereferences/KeepRuleFormatter.java
index c28ef5d..b768c52 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/KeepRuleFormatter.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/KeepRuleFormatter.java
@@ -73,7 +73,7 @@
@Override
protected void printPackageNames(List<String> packageNames) {
if (!packageNames.isEmpty()) {
- append("-keeppackagenames " + StringUtils.join(packageNames, ",") + System.lineSeparator());
+ append("-keeppackagenames " + StringUtils.join(",", packageNames) + System.lineSeparator());
}
}
diff --git a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
index 039f28d..16a6bfc 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
@@ -301,7 +301,7 @@
addType(field.type);
DexEncodedField baseField = appInfo.resolveField(field).getResolvedField();
if (baseField != null && baseField.getHolderType() != field.holder) {
- field = baseField.field;
+ field = baseField.getReference();
}
addType(field.holder);
TracedFieldImpl tracedField = new TracedFieldImpl(field, baseField);
@@ -381,9 +381,9 @@
ResolutionResult resolutionResult = appInfo.unsafeResolveMethodDueToDexFormat(method);
DexEncodedMethod target =
resolutionResult.isVirtualTarget() ? resolutionResult.getSingleTarget() : null;
- if (target != null && target.method != method) {
+ if (target != null && target.getReference() != method) {
addType(method.holder);
- addMethod(target.method);
+ addMethod(target.getReference());
} else {
addMethod(method);
}
@@ -397,9 +397,9 @@
@Override
public void registerInvokeStatic(DexMethod method) {
DexEncodedMethod target = appInfo.unsafeResolveMethodDueToDexFormat(method).getSingleTarget();
- if (target != null && target.method != method) {
+ if (target != null && target.getReference() != method) {
addType(method.holder);
- addMethod(target.method);
+ addMethod(target.getReference());
} else {
addMethod(method);
}
@@ -456,7 +456,7 @@
}
private void registerField(DexEncodedField field) {
- registerTypeReference(field.field.type);
+ registerTypeReference(field.getReference().type);
}
private void registerMethod(ProgramMethod method) {
@@ -488,10 +488,11 @@
clazz.forEachMethod(
method -> {
ResolutionResult resolutionResult =
- appInfo.resolveMethodOn(superType, method.method, superType != clazz.superType);
+ appInfo.resolveMethodOn(
+ superType, method.getReference(), superType != clazz.superType);
DexEncodedMethod dexEncodedMethod = resolutionResult.getSingleTarget();
if (dexEncodedMethod != null) {
- addMethod(dexEncodedMethod.method);
+ addMethod(dexEncodedMethod.getReference());
}
});
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index d1f6e4c..d58387f 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -510,7 +510,7 @@
for (String mainDexClass : getMainDexClasses()) {
mainDexList.add(mainDexClass.replace(".", "/") + CLASS_EXTENSION);
}
- String join = StringUtils.join(mainDexList, "\n");
+ String join = StringUtils.join("\n", mainDexList);
writeToZipStream(out, dumpMainDexListResourceFileName, join.getBytes(), ZipEntry.DEFLATED);
}
if (options.hasMainDexKeepRules()) {
diff --git a/src/main/java/com/android/tools/r8/utils/BooleanBox.java b/src/main/java/com/android/tools/r8/utils/BooleanBox.java
index f6b790d..5ad9494 100644
--- a/src/main/java/com/android/tools/r8/utils/BooleanBox.java
+++ b/src/main/java/com/android/tools/r8/utils/BooleanBox.java
@@ -9,6 +9,7 @@
public class BooleanBox {
private boolean value;
+ private boolean assigned = false;
public BooleanBox() {}
@@ -39,10 +40,23 @@
}
public void set(boolean value) {
+ assigned = true;
this.value = value;
}
public void unset() {
set(false);
}
+
+ public void and(boolean value) {
+ set(value && this.value);
+ }
+
+ public void or(boolean value) {
+ set(value || this.value);
+ }
+
+ public boolean isAssigned() {
+ return assigned;
+ }
}
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 c885d9e..23d71ee 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassMap.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassMap.java
@@ -120,9 +120,7 @@
* has to be run at a join point, concurrent accesses may be confused.
*/
public void clearType(DexType type) {
- if (classes.containsKey(type)) {
- classes.remove(type);
- }
+ classes.remove(type);
ClassProvider<T> provider = classProvider.get();
if (provider == null) {
return;
diff --git a/src/main/java/com/android/tools/r8/utils/ClassProvider.java b/src/main/java/com/android/tools/r8/utils/ClassProvider.java
index af272b8..e46606e 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassProvider.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassProvider.java
@@ -72,7 +72,7 @@
}
public FilteringClassProvider<T> without(Set<DexType> filteredTypes) {
- return new FilteringClassProvider(classKind, this, filteredTypes);
+ return new FilteringClassProvider<>(classKind, this, filteredTypes);
}
/** Create class provider for preloaded classes. */
@@ -167,7 +167,7 @@
public FilteringClassProvider<T> without(Set<DexType> filteredTypes) {
ImmutableSet<DexType> newSet =
ImmutableSet.<DexType>builder().addAll(filteredOut).addAll(filteredTypes).build();
- return new FilteringClassProvider(getClassKind(), provider, newSet);
+ return new FilteringClassProvider<>(getClassKind(), provider, newSet);
}
@Override
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 54bbbcc..7a99160 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -270,8 +270,6 @@
public boolean encodeChecksums = false;
public BiPredicate<String, Long> dexClassChecksumFilter = (name, checksum) -> true;
public boolean cfToCfDesugar = false;
- // TODO(b/172496438): Temporarily enable publicizing package-private overrides.
- public boolean enablePackagePrivateAwarePublicization = false;
public int callGraphLikelySpuriousCallEdgeThreshold = 50;
@@ -1909,4 +1907,12 @@
public boolean canHaveSwitchMaxIntBug() {
return isGeneratingDex() && minApiLevel < AndroidApiLevel.K.getLevel();
}
+
+ // On Dalvik the methods Integer.parseInt and Long.parseLong does not support strings with a '+'
+ // prefix
+ //
+ // See b/182137865.
+ public boolean canParseNumbersWithPlusPrefix() {
+ return minApiLevel > AndroidApiLevel.K.getLevel();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/IterableUtils.java b/src/main/java/com/android/tools/r8/utils/IterableUtils.java
index ce8396f..1354a33 100644
--- a/src/main/java/com/android/tools/r8/utils/IterableUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/IterableUtils.java
@@ -12,6 +12,7 @@
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -151,4 +152,10 @@
}
return !iterator.hasNext();
}
+
+ public static <T, R> Iterable<R> fromMethod(Consumer<Consumer<T>> method, Function<T, R> mapper) {
+ List<R> ts = new ArrayList<>();
+ method.accept(t -> ts.add(mapper.apply(t)));
+ return ts;
+ }
}
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 b1099e1..47ccd91 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -357,11 +357,12 @@
}
}
- DexMethod originalMethod = appView.graphLens().getOriginalMethodSignature(method.method);
+ DexMethod originalMethod =
+ appView.graphLens().getOriginalMethodSignature(method.getReference());
MethodSignature originalSignature =
MethodSignature.fromDexMethod(originalMethod, originalMethod.holder != originalType);
- DexString obfuscatedNameDexString = namingLens.lookupName(method.method);
+ DexString obfuscatedNameDexString = namingLens.lookupName(method.getReference());
String obfuscatedName = obfuscatedNameDexString.toString();
// Add simple "a() -> b" mapping if we won't have any other with concrete line numbers
@@ -467,7 +468,7 @@
}
allSeenAreInstanceInitializers = false;
// If the method is pinned, we cannot minify it.
- if (!keepInfo.isMinificationAllowed(method.method, appView, appView.options())) {
+ if (!keepInfo.isMinificationAllowed(method.getReference(), appView, appView.options())) {
continue;
}
// With desugared library, call-backs names are reserved here.
@@ -477,16 +478,17 @@
// We use the same name for interface names even if it has different types.
DexProgramClass clazz = appView.definitionForProgramType(method.getHolderType());
DexClassAndMethod lookupResult =
- appView.appInfo().lookupMaximallySpecificMethod(clazz, method.method);
+ appView.appInfo().lookupMaximallySpecificMethod(clazz, method.getReference());
if (lookupResult == null) {
// We cannot rename methods we cannot look up.
continue;
}
- String errorString = method.method.qualifiedName() + " is not kept but is overloaded";
+ String errorString = method.getReference().qualifiedName() + " is not kept but is overloaded";
assert lookupResult.getHolder().isInterface() : errorString;
// TODO(b/159113601): Reenable assert.
- assert true || originalName == null || originalName.equals(method.method.name) : errorString;
- originalName = method.method.name;
+ assert true || originalName == null || originalName.equals(method.getReference().name)
+ : errorString;
+ originalName = method.getReference().name;
}
return true;
}
@@ -544,7 +546,7 @@
Supplier<Builder> onDemandClassNamingBuilder) {
clazz.forEachField(
dexEncodedField -> {
- DexField dexField = dexEncodedField.field;
+ DexField dexField = dexEncodedField.getReference();
DexField originalField = graphLens.getOriginalFieldSignature(dexField);
DexString renamedName = namingLens.lookupName(dexField);
if (renamedName != originalField.name || originalField.holder != originalType) {
@@ -562,7 +564,7 @@
new IdentityHashMap<>(clazz.getMethodCollection().size());
for (DexEncodedMethod encodedMethod : clazz.methods()) {
// Add method only if renamed, moved, or contains positions.
- DexMethod method = encodedMethod.method;
+ DexMethod method = encodedMethod.getReference();
DexString renamedName = namingLens.lookupName(method);
if (renamedName != method.name
|| graphLens.getOriginalMethodSignature(method) != method
@@ -626,7 +628,7 @@
PositionEventEmitter positionEventEmitter =
new PositionEventEmitter(
application.dexItemFactory,
- appView.graphLens().getOriginalMethodSignature(method.method),
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
processedEvents);
Box<Boolean> inlinedOriginalPosition = new Box<>(false);
@@ -634,7 +636,8 @@
// Debug event visitor to map line numbers.
DexDebugEventVisitor visitor =
new DexDebugPositionState(
- debugInfo.startLine, appView.graphLens().getOriginalMethodSignature(method.method)) {
+ debugInfo.startLine,
+ appView.graphLens().getOriginalMethodSignature(method.getReference())) {
// Keep track of what PC has been emitted.
private int emittedPc = 0;
@@ -734,7 +737,7 @@
Pair<Integer, Position> lastPosition = new Pair<>();
DexDebugEventVisitor visitor =
- new DexDebugPositionState(debugInfo.startLine, method.method) {
+ new DexDebugPositionState(debugInfo.startLine, method.getReference()) {
@Override
public void visit(Default defaultEvent) {
super.visit(defaultEvent);
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
index fff5425..8c3e592 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
@@ -62,10 +62,7 @@
// All other conflicts are reported as a fatal error.
return (DexProgramClass a, DexProgramClass b) -> {
assert a.type == b.type;
- if (a.originatesFromDexResource()
- && b.originatesFromDexResource()
- && a.accessFlags.isSynthetic()
- && b.accessFlags.isSynthetic()) {
+ if (a.accessFlags.isSynthetic() && b.accessFlags.isSynthetic()) {
return mergeClasses(reporter, a, b);
}
throw reportDuplicateTypes(reporter, a, b);
@@ -82,7 +79,8 @@
private static DexProgramClass mergeClasses(
Reporter reporter, DexProgramClass a, DexProgramClass b) {
- if (a.type.isLegacySynthesizedTypeAllowedDuplication()) {
+ if (a.type.isLegacySynthesizedTypeAllowedDuplication()
+ || a.type.isSynthesizedTypeAllowedDuplication()) {
assert assertEqualClasses(a, b);
return a;
}
diff --git a/src/main/java/com/android/tools/r8/utils/StringUtils.java b/src/main/java/com/android/tools/r8/utils/StringUtils.java
index 8f398ac..9be7a5e 100644
--- a/src/main/java/com/android/tools/r8/utils/StringUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/StringUtils.java
@@ -124,20 +124,20 @@
return builder;
}
- public static <T> String join(Collection<T> collection, String separator) {
- return join(collection, separator, BraceType.NONE);
+ public static String join(String separator, String... strings) {
+ return join(separator, Arrays.asList(strings));
+ }
+
+ public static <T> String join(String separator, Iterable<T> iterable) {
+ return join(separator, iterable, BraceType.NONE);
}
public static <T> String join(String separator, Iterable<T> iterable, Function<T, String> fn) {
return join(separator, iterable, fn, BraceType.NONE);
}
- public static String join(String separator, String... strings) {
- return join(Arrays.asList(strings), separator, BraceType.NONE);
- }
-
- public static <T> String join(Collection<T> collection, String separator, BraceType brace) {
- return join(separator, collection, Object::toString, brace);
+ public static <T> String join(String separator, Iterable<T> iterable, BraceType brace) {
+ return join(separator, iterable, Object::toString, brace);
}
public static <T> String join(
@@ -174,7 +174,7 @@
}
public static <T> String joinLines(Collection<T> collection) {
- return join(collection, LINE_SEPARATOR, BraceType.NONE);
+ return join(LINE_SEPARATOR, collection, BraceType.NONE);
}
public static List<String> splitLines(String content) {
diff --git a/src/main/java/com/android/tools/r8/utils/WorkList.java b/src/main/java/com/android/tools/r8/utils/WorkList.java
index e5fb33f..4279cb7 100644
--- a/src/main/java/com/android/tools/r8/utils/WorkList.java
+++ b/src/main/java/com/android/tools/r8/utils/WorkList.java
@@ -27,7 +27,7 @@
}
public static <T> WorkList<T> newIdentityWorkList() {
- return new WorkList<T>(EqualityTest.IDENTITY);
+ return new WorkList<>(EqualityTest.IDENTITY);
}
public static <T> WorkList<T> newIdentityWorkList(T item) {
@@ -60,7 +60,7 @@
items.forEach(workingList::addLast);
}
- public void addIfNotSeen(Iterable<T> items) {
+ public void addIfNotSeen(Iterable<? extends T> items) {
items.forEach(this::addIfNotSeen);
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java
index b75d224..1e53a14 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java
@@ -17,11 +17,11 @@
private final Map<K, V> backing;
private final Map<V, Set<K>> inverse;
- public BidirectionalManyToOneHashMap() {
- this(new IdentityHashMap<>(), new IdentityHashMap<>());
+ public static <K, V> BidirectionalManyToOneHashMap<K, V> newIdentityHashMap() {
+ return new BidirectionalManyToOneHashMap<>(new IdentityHashMap<>(), new IdentityHashMap<>());
}
- private BidirectionalManyToOneHashMap(Map<K, V> backing, Map<V, Set<K>> inverse) {
+ protected BidirectionalManyToOneHashMap(Map<K, V> backing, Map<V, Set<K>> inverse) {
this.backing = backing;
this.inverse = inverse;
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java
index 4c2f3a8..ffd653e 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneRepresentativeHashMap.java
@@ -13,7 +13,18 @@
extends BidirectionalManyToOneHashMap<K, V>
implements MutableBidirectionalManyToOneRepresentativeMap<K, V> {
- private final Map<V, K> representatives = new IdentityHashMap<>();
+ private final Map<V, K> representatives;
+
+ public static <K, V> BidirectionalManyToOneRepresentativeHashMap<K, V> newIdentityHashMap() {
+ return new BidirectionalManyToOneRepresentativeHashMap<>(
+ new IdentityHashMap<>(), new IdentityHashMap<>(), new IdentityHashMap<>());
+ }
+
+ private BidirectionalManyToOneRepresentativeHashMap(
+ Map<K, V> backing, Map<V, Set<K>> inverse, Map<V, K> representatives) {
+ super(backing, inverse);
+ this.representatives = representatives;
+ }
@Override
public void clear() {
diff --git a/src/test/examplesJava9/backport/IntegerBackportJava9Main.java b/src/test/examplesJava9/backport/IntegerBackportJava9Main.java
index 30e9086..8188fe1 100644
--- a/src/test/examplesJava9/backport/IntegerBackportJava9Main.java
+++ b/src/test/examplesJava9/backport/IntegerBackportJava9Main.java
@@ -22,10 +22,10 @@
};
public static void main(String[] args) {
- testParseIntegerSubsequenceWithRadix(args.length == 0 || !args[0].startsWith("4."));
+ testParseIntegerSubsequenceWithRadix();
}
- private static void testParseIntegerSubsequenceWithRadix(boolean supportsPlusPrefix) {
+ private static void testParseIntegerSubsequenceWithRadix() {
for (int value : interestingValues) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx"}) {
@@ -34,7 +34,7 @@
int start = prefix.length();
int end = valueString.length() - postfix.length();
assertEquals(valueString, value, Integer.parseInt(valueString, start, end, radix));
- if (value > 0 && supportsPlusPrefix) {
+ if (value > 0) {
valueString = prefix + '+' + Long.toString(value, radix) + postfix;
end++;
assertEquals(valueString, value, Integer.parseInt(valueString, start, end, radix));
@@ -45,24 +45,29 @@
}
try {
- throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
+ throw new AssertionError(Integer.parseInt("0", 0, 1, Character.MIN_RADIX - 1));
} catch (IllegalArgumentException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
+ throw new AssertionError(Integer.parseInt("0", 0, 1, Character.MAX_RADIX + 1));
} catch (IllegalArgumentException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
+ throw new AssertionError(Integer.parseInt("", 0, 0, 16));
} catch (NumberFormatException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("-", 0, 1, 16));
+ throw new AssertionError(Integer.parseInt("-", 0, 1, 16));
} catch (NumberFormatException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
+ throw new AssertionError(Integer.parseInt("+", 0, 1, 16));
+ } catch (NumberFormatException expected) {
+ }
+
+ try {
+ throw new AssertionError(Integer.parseInt("+a", 0, 2, 10));
} catch (NumberFormatException expected) {
}
diff --git a/src/test/examplesJava9/backport/LongBackportJava9Main.java b/src/test/examplesJava9/backport/LongBackportJava9Main.java
index 1634a43..f24c337 100644
--- a/src/test/examplesJava9/backport/LongBackportJava9Main.java
+++ b/src/test/examplesJava9/backport/LongBackportJava9Main.java
@@ -24,11 +24,11 @@
};
public static void main(String[] args) {
- testParseLongSubsequenceWithRadix(args.length == 0 || !args[0].startsWith("4."));
+ testParseLongSubsequenceWithRadix();
testParseUnsignedLongSubsequenceWithRadix();
}
- private static void testParseLongSubsequenceWithRadix(boolean supportsPlusPrefix) {
+ private static void testParseLongSubsequenceWithRadix() {
for (long value : interestingValues) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx"}) {
@@ -37,7 +37,7 @@
int start = prefix.length();
int end = valueString.length() - postfix.length();
assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
- if (value > 0 && supportsPlusPrefix) {
+ if (value > 0) {
valueString = prefix + "+" + Long.toString(value, radix) + postfix;
end++;
assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
@@ -48,24 +48,29 @@
}
try {
- throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
+ throw new AssertionError(Long.parseLong("0", 0, 1, Character.MIN_RADIX - 1));
} catch (IllegalArgumentException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
+ throw new AssertionError(Long.parseLong("0", 0, 1, Character.MAX_RADIX + 1));
} catch (IllegalArgumentException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
+ throw new AssertionError(Long.parseLong("", 0, 0, 16));
} catch (NumberFormatException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("-", 0, 1, 16));
+ throw new AssertionError(Long.parseLong("-", 0, 1, 16));
} catch (NumberFormatException expected) {
}
try {
- throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
+ throw new AssertionError(Long.parseLong("+", 0, 1, 16));
+ } catch (NumberFormatException expected) {
+ }
+
+ try {
+ throw new AssertionError(Long.parseLong("+a", 0, 2, 10));
} catch (NumberFormatException expected) {
}
@@ -122,6 +127,11 @@
} catch (NumberFormatException expected) {
}
+ try {
+ throw new AssertionError(Long.parseUnsignedLong("+a", 0, 2, 10));
+ } catch (NumberFormatException expected) {
+ }
+
BigInteger overflow = new BigInteger("18446744073709551616");
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx", "+", "x+", "xxx+"}) {
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
index 8e33480..8e5dd69 100644
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
@@ -95,7 +95,17 @@
ProcessBuilder builder = new ProcessBuilder(command);
ProcessResult result = ToolHelper.runProcess(builder);
assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
- Assert.assertTrue(result.stdout, result.stdout.isEmpty());
- Assert.assertTrue(result.stderr, result.stderr.isEmpty());
+ Assert.assertEquals("", filterOutMainDexListWarnings(result.stdout));
+ Assert.assertEquals("", result.stderr);
+ }
+
+ public static String filterOutMainDexListWarnings(String output) {
+ StringBuilder builder = new StringBuilder();
+ for (String line : output.split("\n")) {
+ if (!line.contains("Unsupported usage of main-dex list")) {
+ builder.append(line).append("\n");
+ }
+ }
+ return builder.toString();
}
}
diff --git a/src/test/java/com/android/tools/r8/DeviceRunner.java b/src/test/java/com/android/tools/r8/DeviceRunner.java
index c68c8f2..fb46cfd 100644
--- a/src/test/java/com/android/tools/r8/DeviceRunner.java
+++ b/src/test/java/com/android/tools/r8/DeviceRunner.java
@@ -167,7 +167,8 @@
throw new DeviceRunnerConfigurationException(
"Running tests on more than one device is not yet supported. "
+ "Currently connected devices: ["
- + StringUtils.join(Arrays.asList(connectedDevices), ",") + "]");
+ + StringUtils.join(",", Arrays.asList(connectedDevices))
+ + "]");
}
int exitStatus = -1;
diff --git a/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java b/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java
index 0700a5f..03ba4b8 100644
--- a/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java
@@ -89,4 +89,9 @@
public GenerateMainDexListTestBuilder addDataEntryResources(DataEntryResource... resources) {
return addDataResources(Arrays.asList(resources));
}
+
+ public GenerateMainDexListTestBuilder setMainDexListOutputPath(Path output) {
+ builder.setMainDexListOutputPath(output);
+ return self();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
index ac3d89f..67753da 100644
--- a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
@@ -4,7 +4,6 @@
package com.android.tools.r8;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -82,7 +81,7 @@
ProcessBuilder builder = new ProcessBuilder(command);
ProcessResult result = ToolHelper.runProcess(builder);
assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
- assertTrue(result.stdout, result.stdout.isEmpty());
- assertTrue(result.stderr, result.stderr.isEmpty());
+ assertEquals("", D8ApiBinaryCompatibilityTests.filterOutMainDexListWarnings(result.stdout));
+ assertEquals("", result.stderr);
}
}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index e1d8658..0d90a34 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -229,7 +229,7 @@
return addMainDexRuleFiles(Arrays.asList(files));
}
- public T addMainDexClassRules(Class<?>... classes) {
+ public T addMainDexKeepClassRules(Class<?>... classes) {
for (Class<?> clazz : classes) {
addMainDexRules("-keep class " + clazz.getTypeName());
}
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index ba56c6f..97b1a5c 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -477,7 +477,7 @@
.add(out.toString())
.build();
Consumer<ArtCommandBuilder> commandConsumer =
- withArt6Plus64BitsLib && vm.getVersion().isAtLeast(DexVm.Version.V6_0_1)
+ withArt6Plus64BitsLib && vm.getVersion().isNewerThanOrEqual(DexVm.Version.V6_0_1)
? builder -> builder.appendArtOption("--64")
: builder -> {};
commandConsumer =
diff --git a/src/test/java/com/android/tools/r8/TestParameters.java b/src/test/java/com/android/tools/r8/TestParameters.java
index be45d1c..5a7423a 100644
--- a/src/test/java/com/android/tools/r8/TestParameters.java
+++ b/src/test/java/com/android/tools/r8/TestParameters.java
@@ -36,6 +36,13 @@
.isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport());
}
+ public boolean canUseDefaultAndStaticInterfaceMethodsWhenDesugaring() {
+ assert isCfRuntime() || isDexRuntime();
+ assert apiLevel != null;
+ return getApiLevel()
+ .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport());
+ }
+
// Convenience predicates.
public boolean isDexRuntime() {
return runtime.isDex();
@@ -49,6 +56,10 @@
return runtime.isCf() && runtime.asCf().getVm() == vm;
}
+ public boolean isDexRuntimeVersion(DexVm.Version vm) {
+ return isDexRuntime() && vm == getDexRuntimeVersion();
+ }
+
public boolean isNoneRuntime() {
return runtime == NoneRuntime.getInstance();
}
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 7721c08..9d0e9b5 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -180,10 +180,12 @@
public static final Path DESUGAR_LIB_CONVERSIONS =
Paths.get(LIBS_DIR, "library_desugar_conversions.zip");
+ public static final String DESUGAR_LIB_JSON_DIR =
+ System.getProperty("desugar_jdk_json_dir", "src/library_desugar");
public static final Path DESUGAR_LIB_JSON_FOR_TESTING =
- Paths.get("src/library_desugar/desugar_jdk_libs.json");
+ Paths.get(DESUGAR_LIB_JSON_DIR, "desugar_jdk_libs.json");
public static final Path DESUGAR_LIB_JSON_FOR_TESTING_ALTERNATIVE_3 =
- Paths.get("src/library_desugar/desugar_jdk_libs_alternative_3.json");
+ Paths.get(DESUGAR_LIB_JSON_DIR, "desugar_jdk_libs_alternative_3.json");
public static boolean isLocalDevelopment() {
return System.getProperty("local_development", "0").equals("1");
@@ -266,7 +268,7 @@
}
public boolean isLatest() {
- return this == V10_0_0;
+ return this == last();
}
public boolean isNewerThan(Version other) {
@@ -277,10 +279,6 @@
return compareTo(other) >= 0;
}
- public boolean isAtLeast(Version other) {
- return compareTo(other) >= 0;
- }
-
public boolean isOlderThan(Version other) {
return compareTo(other) < 0;
}
@@ -289,11 +287,16 @@
return compareTo(other) <= 0;
}
+ public boolean isInRangeInclusive(Version start, Version end) {
+ assert start.isOlderThanOrEqual(end);
+ return isNewerThanOrEqual(start) && isOlderThanOrEqual(end);
+ }
+
public String toString() {
return shortName;
}
- private String shortName;
+ private final String shortName;
public static Version first() {
return V4_0_4;
diff --git a/src/test/java/com/android/tools/r8/VmTestRunner.java b/src/test/java/com/android/tools/r8/VmTestRunner.java
index a3e76a4..e2028a4 100644
--- a/src/test/java/com/android/tools/r8/VmTestRunner.java
+++ b/src/test/java/com/android/tools/r8/VmTestRunner.java
@@ -78,7 +78,7 @@
IgnoreIfVmOlderThan ignoreIfVmOlderThan =
child.getAnnotation(IgnoreIfVmOlderThan.class);
if (ignoreIfVmOlderThan != null
- && !currentVersion.isAtLeast(ignoreIfVmOlderThan.value())) {
+ && !currentVersion.isNewerThanOrEqual(ignoreIfVmOlderThan.value())) {
return true;
}
IgnoreIfVmOlderOrEqualThan ignoreIfVmOlderOrEqualThan =
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerBottomTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerBottomTest.java
index 3c71dbe..6dc8328 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerBottomTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerBottomTest.java
@@ -4,6 +4,10 @@
package com.android.tools.r8.accessrelaxation;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
@@ -12,6 +16,8 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -58,8 +64,17 @@
.enableNeverClassInliningAnnotations()
.allowAccessModification()
.run(parameters.getRuntime(), Main.class)
- // TODO(b/181328496): This should be EXPECTED.
- .assertSuccessWithOutputLines(EXPECTED_ART_4);
+ // TODO(b/182185057): This is an error in the devirtualizer
+ .assertSuccessWithOutputLines(EXPECTED_ART_4)
+ .inspect(
+ inspector -> {
+ ClassSubject subViewModelSubject =
+ inspector.clazz(DescriptorUtils.descriptorToJavaType(NEW_DESCRIPTOR));
+ assertThat(subViewModelSubject, isPresent());
+ MethodSubject clearSubject = subViewModelSubject.uniqueMethodWithName("clear");
+ assertThat(clearSubject, isPresent());
+ assertTrue(clearSubject.isPublic());
+ });
}
private byte[] getSubViewModelInAnotherPackage() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerTest.java
index 5a9da04..ccd0b21 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/PackagePrivateOverridePublicizerTest.java
@@ -23,7 +23,6 @@
private final TestParameters parameters;
private final String[] EXPECTED = new String[] {"SubViewModel.clear()", "ViewModel.clear()"};
- private final String[] R8_OUT = new String[] {"SubViewModel.clear()", "SubViewModel.clear()"};
@Parameters(name = "{0}")
public static TestParametersCollection data() {
@@ -52,8 +51,7 @@
.enableNeverClassInliningAnnotations()
.allowAccessModification()
.run(parameters.getRuntime(), Main.class)
- // TODO(b/172496438): This should be EXPECTED.
- .assertSuccessWithOutputLines(R8_OUT);
+ .apply(this::assertSuccessOutput);
}
private void assertSuccessOutput(TestRunResult<?> result) {
diff --git a/src/test/java/com/android/tools/r8/cf/stackmap/UninitializedInstanceOfTest.java b/src/test/java/com/android/tools/r8/cf/stackmap/UninitializedInstanceOfTest.java
index 30b2a78..492e21e 100644
--- a/src/test/java/com/android/tools/r8/cf/stackmap/UninitializedInstanceOfTest.java
+++ b/src/test/java/com/android/tools/r8/cf/stackmap/UninitializedInstanceOfTest.java
@@ -59,7 +59,7 @@
@Test()
public void testD8Dex() throws Exception {
assumeTrue(parameters.isDexRuntime());
- boolean expectFailure = parameters.getDexRuntimeVersion().isAtLeast(Version.V7_0_0);
+ boolean expectFailure = parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V7_0_0);
testForD8(parameters.getBackend())
.addProgramClassFileData(dump())
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
index fcc79dc..2c58d15 100644
--- a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
@@ -111,7 +111,7 @@
continue;
}
String holderName = method.getHolderType().getName();
- String methodName = method.method.name.toString();
+ String methodName = method.getReference().name.toString();
String generatedMethodName = holderName + "_" + methodName;
CfCode code = getCode(holderName, methodName, method.getCode().asCfCode());
if (code != null) {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingNonTrivialTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingNonTrivialTest.java
index 42df5c0..fbd058a 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingNonTrivialTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingNonTrivialTest.java
@@ -12,9 +12,8 @@
public class AbstractMethodMergingNonTrivialTest extends HorizontalClassMergingTestBase {
- public AbstractMethodMergingNonTrivialTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public AbstractMethodMergingNonTrivialTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,11 +21,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.enableInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.enableNoVerticalClassMergingAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingTest.java
index 3b0af4f..a30ca9e 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/AbstractMethodMergingTest.java
@@ -12,9 +12,8 @@
public class AbstractMethodMergingTest extends HorizontalClassMergingTestBase {
- public AbstractMethodMergingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public AbstractMethodMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,11 +21,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.enableInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.enableNoVerticalClassMergingAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptResourceFileContentsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptResourceFileContentsTest.java
index db8d4c7..cdd0df8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptResourceFileContentsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptResourceFileContentsTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -23,9 +23,8 @@
import org.junit.Test;
public class AdaptResourceFileContentsTest extends HorizontalClassMergingTestBase {
- public AdaptResourceFileContentsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public AdaptResourceFileContentsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -35,9 +34,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addOptionsModification(options -> options.dataResourceConsumer = dataResourceConsumer)
.enableNeverClassInliningAnnotations()
.addDataEntryResources(
@@ -45,8 +41,7 @@
"foo.txt", Origin.unknown(), A.class.getTypeName(), B.class.getTypeName()))
.addKeepRules("-adaptresourcefilecontents foo.txt")
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertMergedInto(B.class, A.class))
.compile()
.run(parameters.getRuntime(), Main.class)
@@ -57,11 +52,10 @@
assertThat(aClassSubject, isPresent());
ClassSubject bClassSubject = codeInspector.clazz(B.class);
- assertThat(bClassSubject, notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(bClassSubject, isAbsent());
// Check that the class name has been rewritten.
- String newClassBName =
- (enableHorizontalClassMerging ? aClassSubject : bClassSubject).getFinalName();
+ String newClassBName = aClassSubject.getFinalName();
assertEquals(
dataResourceConsumer.get("foo.txt"),
ImmutableList.of(aClassSubject.getFinalName(), newClassBName));
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptVerticallyMergedResourceFileContentsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptVerticallyMergedResourceFileContentsTest.java
index 090cb9e..1cbf805 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptVerticallyMergedResourceFileContentsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/AdaptVerticallyMergedResourceFileContentsTest.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -21,9 +20,8 @@
import org.junit.Test;
public class AdaptVerticallyMergedResourceFileContentsTest extends HorizontalClassMergingTestBase {
- public AdaptVerticallyMergedResourceFileContentsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public AdaptVerticallyMergedResourceFileContentsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -33,9 +31,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addOptionsModification(options -> options.dataResourceConsumer = dataResourceConsumer)
.enableNeverClassInliningAnnotations()
.addDataEntryResources(
@@ -47,8 +42,7 @@
B.class.getTypeName()))
.addKeepRules("-adaptresourcefilecontents foo.txt")
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertMergedInto(B.class, A.class))
.addVerticallyMergedClassesInspector(
inspector -> inspector.assertMergedIntoSubtype(Parent.class))
@@ -63,11 +57,10 @@
assertThat(aClassSubject, isPresent());
ClassSubject bClassSubject = codeInspector.clazz(B.class);
- assertThat(bClassSubject, notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(bClassSubject, not(isPresent()));
// Check that the class name has been rewritten.
- String newClassName =
- (enableHorizontalClassMerging ? aClassSubject : bClassSubject).getFinalName();
+ String newClassName = aClassSubject.getFinalName();
assertEquals(
dataResourceConsumer.get("foo.txt"),
ImmutableList.of(aClassSubject.getFinalName(), aClassSubject.getFinalName(), newClassName));
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassWithInstanceFieldsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassWithInstanceFieldsTest.java
index 31a49cc..41071d8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassWithInstanceFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassWithInstanceFieldsTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -14,9 +14,8 @@
import org.junit.Test;
public class ClassWithInstanceFieldsTest extends HorizontalClassMergingTestBase {
- public ClassWithInstanceFieldsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassWithInstanceFieldsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,21 +23,17 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.enableInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("A. field: 5, v: a, j: 1", "B. field: b, v: 2, j: 3")
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java
index bc5380e..bbf9149 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java
@@ -13,9 +13,8 @@
import org.junit.Test;
public class ClassesDistinguishedByDirectCheckCastTest extends HorizontalClassMergingTestBase {
- public ClassesDistinguishedByDirectCheckCastTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesDistinguishedByDirectCheckCastTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -23,9 +22,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java
index 6551ad2..d380c43 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java
@@ -13,9 +13,8 @@
import org.junit.Test;
public class ClassesDistinguishedByDirectInstanceOfTest extends HorizontalClassMergingTestBase {
- public ClassesDistinguishedByDirectInstanceOfTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesDistinguishedByDirectInstanceOfTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -23,9 +22,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java
index 6017cbe..9847ac8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java
@@ -15,9 +15,8 @@
public class ClassesDistinguishedByIndirectCheckCastToInterfaceTest
extends HorizontalClassMergingTestBase {
- public ClassesDistinguishedByIndirectCheckCastToInterfaceTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesDistinguishedByIndirectCheckCastToInterfaceTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +24,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNoVerticalClassMergingAnnotations()
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java
index cf05da6..8bf955c 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java
@@ -15,9 +15,8 @@
public class ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast
extends HorizontalClassMergingTestBase {
- public ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +24,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.enableNeverClassInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentFieldsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentFieldsTest.java
index d322729..7e90337 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentFieldsTest.java
@@ -6,8 +6,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -16,9 +16,8 @@
import org.junit.Test;
public class ClassesWithDifferentFieldsTest extends HorizontalClassMergingTestBase {
- public ClassesWithDifferentFieldsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithDifferentFieldsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,22 +25,18 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.enableInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.compile()
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("A. v: a", "B. i: 2")
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentInterfacesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentInterfacesTest.java
index 5abdc09..497e4df 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentInterfacesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentInterfacesTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -15,9 +15,8 @@
import org.junit.Test;
public class ClassesWithDifferentInterfacesTest extends HorizontalClassMergingTestBase {
- public ClassesWithDifferentInterfacesTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithDifferentInterfacesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,15 +24,12 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(Z.class, Y.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(Z.class, Y.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("bar", "foo y", "bar")
.inspect(
@@ -41,8 +37,7 @@
assertThat(codeInspector.clazz(I.class), isPresent());
assertThat(codeInspector.clazz(X.class), isPresent());
assertThat(codeInspector.clazz(Y.class), isPresent());
- assertThat(
- codeInspector.clazz(Z.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(Z.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentVisibilityFieldsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentVisibilityFieldsTest.java
index 68a81b1..269b793 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentVisibilityFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithDifferentVisibilityFieldsTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static com.android.tools.r8.utils.codeinspector.Matchers.readsInstanceField;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -21,9 +21,8 @@
import org.junit.Test;
public class ClassesWithDifferentVisibilityFieldsTest extends HorizontalClassMergingTestBase {
- public ClassesWithDifferentVisibilityFieldsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithDifferentVisibilityFieldsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -31,14 +30,11 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(
"a. v1: 10, v2: 20", "b. v1: 60, v2: 100", "c. v1: 210, v2: 330")
@@ -46,31 +42,28 @@
codeInspector -> {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
assertThat(codeInspector.clazz(C.class), isPresent());
- if (enableHorizontalClassMerging) {
- FieldSubject v1Subject = aClassSubject.uniqueFieldWithName("v1");
- FieldSubject v2Subject = aClassSubject.uniqueFieldWithName("v2");
+ FieldSubject v1Subject = aClassSubject.uniqueFieldWithName("v1");
+ FieldSubject v2Subject = aClassSubject.uniqueFieldWithName("v2");
- MethodSubject methodSubject = aClassSubject.uniqueMethodWithName("getAV1");
- assertThat(methodSubject, isPresent());
- assertThat(methodSubject, readsInstanceField(v1Subject.getDexField()));
+ MethodSubject methodSubject = aClassSubject.uniqueMethodWithName("getAV1");
+ assertThat(methodSubject, isPresent());
+ assertThat(methodSubject, readsInstanceField(v1Subject.getDexField()));
- methodSubject = aClassSubject.uniqueMethodWithName("getAV2");
- assertThat(methodSubject, isPresent());
- assertThat(methodSubject, readsInstanceField(v2Subject.getDexField()));
+ methodSubject = aClassSubject.uniqueMethodWithName("getAV2");
+ assertThat(methodSubject, isPresent());
+ assertThat(methodSubject, readsInstanceField(v2Subject.getDexField()));
- // The fields v1 and v2 are swapped, because their access modifiers are swapped.
- methodSubject = aClassSubject.uniqueMethodWithName("getBV1");
- assertThat(methodSubject, isPresent());
- assertThat(methodSubject, readsInstanceField(v2Subject.getDexField()));
+ // The fields v1 and v2 are swapped, because their access modifiers are swapped.
+ methodSubject = aClassSubject.uniqueMethodWithName("getBV1");
+ assertThat(methodSubject, isPresent());
+ assertThat(methodSubject, readsInstanceField(v2Subject.getDexField()));
- methodSubject = aClassSubject.uniqueMethodWithName("getBV2");
- assertThat(methodSubject, isPresent());
- assertThat(methodSubject, readsInstanceField(v1Subject.getDexField()));
- }
+ methodSubject = aClassSubject.uniqueMethodWithName("getBV2");
+ assertThat(methodSubject, isPresent());
+ assertThat(methodSubject, readsInstanceField(v1Subject.getDexField()));
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithFeatureSplitTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithFeatureSplitTest.java
index 9ac569b..3f0fac0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithFeatureSplitTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithFeatureSplitTest.java
@@ -5,30 +5,26 @@
package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.dexsplitter.SplitterTestBase.RunInterface;
-import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.List;
import org.junit.Test;
import org.junit.runners.Parameterized;
public class ClassesWithFeatureSplitTest extends HorizontalClassMergingTestBase {
- public ClassesWithFeatureSplitTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithFeatureSplitTest(TestParameters parameters) {
+ super(parameters);
}
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withDexRuntimes().withAllApiLevels().build(), BooleanUtils.values());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
}
@Test
@@ -41,9 +37,6 @@
.addFeatureSplit(Feature2Class.class, Feature2Main.class)
.addKeepFeatureMainRule(Feature1Main.class)
.addKeepFeatureMainRule(Feature2Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.compile()
@@ -68,8 +61,7 @@
private void inspectFeature1(CodeInspector inspector) {
assertThat(inspector.clazz(Feature1Main.class), isPresent());
assertThat(inspector.clazz(Feature1Class1.class), isPresent());
- assertThat(
- inspector.clazz(Feature1Class2.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(inspector.clazz(Feature1Class2.class), not(isPresent()));
assertThat(inspector.clazz(Feature2Main.class), not(isPresent()));
assertThat(inspector.clazz(Feature2Class.class), not(isPresent()));
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithIdenticalInterfacesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithIdenticalInterfacesTest.java
index 6714388..9a5f503 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithIdenticalInterfacesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithIdenticalInterfacesTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -14,9 +14,8 @@
import org.junit.Test;
public class ClassesWithIdenticalInterfacesTest extends HorizontalClassMergingTestBase {
- public ClassesWithIdenticalInterfacesTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithIdenticalInterfacesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,14 +23,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
inspector.assertMergedInto(Y.class, X.class).assertMergedInto(Z.class, X.class))
.run(parameters.getRuntime(), Main.class)
@@ -40,10 +35,8 @@
codeInspector -> {
assertThat(codeInspector.clazz(I.class), isPresent());
assertThat(codeInspector.clazz(X.class), isPresent());
- assertThat(
- codeInspector.clazz(Y.class), notIf(isPresent(), enableHorizontalClassMerging));
- assertThat(
- codeInspector.clazz(Z.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(Y.class), isAbsent());
+ assertThat(codeInspector.clazz(Z.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithNativeMethodsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithNativeMethodsTest.java
index c551a26..dcdd8f8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithNativeMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithNativeMethodsTest.java
@@ -16,9 +16,8 @@
import org.junit.Test;
public class ClassesWithNativeMethodsTest extends HorizontalClassMergingTestBase {
- public ClassesWithNativeMethodsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithNativeMethodsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,9 +25,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java
index 608f6fe..db0ce63 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithOverlappingVisibilitiesTest.java
@@ -4,10 +4,10 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPackagePrivate;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPublic;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -18,9 +18,8 @@
import org.junit.Test;
public class ClassesWithOverlappingVisibilitiesTest extends HorizontalClassMergingTestBase {
- public ClassesWithOverlappingVisibilitiesTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithOverlappingVisibilitiesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -28,9 +27,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -45,23 +41,18 @@
ClassSubject bClassSubject = codeInspector.clazz(B.class);
assertThat(bClassSubject, isPresent());
- if (enableHorizontalClassMerging) {
- methodSubject = bClassSubject.method("void", "foo$bridge");
- assertThat(methodSubject, isPackagePrivate());
- }
+ methodSubject = bClassSubject.method("void", "foo$bridge");
+ assertThat(methodSubject, isPackagePrivate());
- assertThat(
- codeInspector.clazz(C.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(C.class), isAbsent());
ClassSubject dClassSubject = codeInspector.clazz(D.class);
assertThat(dClassSubject, isPresent());
- if (enableHorizontalClassMerging) {
- methodSubject = dClassSubject.method("void", "foo$bridge");
- assertThat(methodSubject, isPublic());
- }
+ methodSubject = dClassSubject.method("void", "foo$bridge");
+ assertThat(methodSubject, isPublic());
ClassSubject eClassSubject = codeInspector.clazz(E.class);
- assertThat(eClassSubject, notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(eClassSubject, isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithStaticFields.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithStaticFields.java
index 2810ce8..d66a630 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithStaticFields.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesWithStaticFields.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -13,8 +13,8 @@
import org.junit.Test;
public class ClassesWithStaticFields extends HorizontalClassMergingTestBase {
- public ClassesWithStaticFields(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ClassesWithStaticFields(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,20 +22,16 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("a: 0", "b: 0", "a: 1", "b: 1")
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/CompanionClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/CompanionClassMergingTest.java
index 9aca9fe..364f7ed 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/CompanionClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/CompanionClassMergingTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -16,9 +16,8 @@
import org.junit.Test;
public class CompanionClassMergingTest extends HorizontalClassMergingTestBase {
- public CompanionClassMergingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public CompanionClassMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,14 +25,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addOptionsModification(options -> options.enableClassInlining = false)
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertMergedInto(B.Companion.class, A.Companion.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("foo a 0", "foo b 1")
@@ -43,9 +38,7 @@
assertThat(codeInspector.clazz(B.class), isPresent());
assertThat(codeInspector.clazz(A.Companion.class), isPresent());
- assertThat(
- codeInspector.clazz(B.Companion.class),
- notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.Companion.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/CompatKeepConstructorLiveTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/CompatKeepConstructorLiveTest.java
index c03361f..ccec2d8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/CompatKeepConstructorLiveTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/CompatKeepConstructorLiveTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -14,9 +14,8 @@
import org.junit.Test;
public class CompatKeepConstructorLiveTest extends HorizontalClassMergingTestBase {
- public CompatKeepConstructorLiveTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public CompatKeepConstructorLiveTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,9 +23,6 @@
testForR8Compat(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
@@ -39,8 +35,7 @@
assertThat(aClassSubject.init(), isPresent());
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorCantInlineTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorCantInlineTest.java
index 369ebfd..07cea40 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorCantInlineTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorCantInlineTest.java
@@ -5,20 +5,17 @@
package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.TestParameters;
import org.junit.Test;
public class ConstructorCantInlineTest extends HorizontalClassMergingTestBase {
- public ConstructorCantInlineTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorCantInlineTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,9 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -39,8 +33,7 @@
assertThat(codeInspector.clazz(A.class), not(isPresent()));
assertThat(codeInspector.clazz(B.class), isPresent());
assertThat(codeInspector.clazz(C.class), isPresent());
- assertThat(
- codeInspector.clazz(D.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(D.class), not(isPresent()));
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingAfterUnusedArgumentRemovalTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingAfterUnusedArgumentRemovalTest.java
index d38efb3..fd1a5ac 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingAfterUnusedArgumentRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingAfterUnusedArgumentRemovalTest.java
@@ -11,9 +11,8 @@
public class ConstructorMergingAfterUnusedArgumentRemovalTest
extends HorizontalClassMergingTestBase {
- public ConstructorMergingAfterUnusedArgumentRemovalTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorMergingAfterUnusedArgumentRemovalTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -21,13 +20,9 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
inspector
.assertMergedInto(B.class, A.class)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java
index 8936dc1..055ab8d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingOverlapTest.java
@@ -21,9 +21,8 @@
public class ConstructorMergingOverlapTest extends HorizontalClassMergingTestBase {
- public ConstructorMergingOverlapTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorMergingOverlapTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -31,9 +30,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -41,7 +37,6 @@
.assertSuccessWithOutputLines("42", "13", "7", "print a", "print b")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
FieldSubject classIdFieldSubject =
@@ -66,12 +61,6 @@
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
assertThat(codeInspector.clazz(B.class), not(isPresent()));
-
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
index 4d62a05..e0c6c9e 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingPreoptimizedTest.java
@@ -22,9 +22,8 @@
public class ConstructorMergingPreoptimizedTest extends HorizontalClassMergingTestBase {
- public ConstructorMergingPreoptimizedTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorMergingPreoptimizedTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -32,11 +31,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
@@ -46,38 +42,29 @@
"changed", "13", "42", "foo", "7", "foo", "print a", "print b")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
- ClassSubject changedClassSubject = codeInspector.clazz(Changed.class);
- assertThat(changedClassSubject, isPresent());
+ ClassSubject changedClassSubject = codeInspector.clazz(Changed.class);
+ assertThat(changedClassSubject, isPresent());
- ClassSubject aClassSubject = codeInspector.clazz(A.class);
- assertThat(aClassSubject, isPresent());
- FieldSubject classIdFieldSubject =
- aClassSubject.uniqueFieldWithName(ClassMerger.CLASS_ID_FIELD_NAME);
- assertThat(classIdFieldSubject, isPresent());
+ ClassSubject aClassSubject = codeInspector.clazz(A.class);
+ assertThat(aClassSubject, isPresent());
+ FieldSubject classIdFieldSubject =
+ aClassSubject.uniqueFieldWithName(ClassMerger.CLASS_ID_FIELD_NAME);
+ assertThat(classIdFieldSubject, isPresent());
- MethodSubject firstInitSubject = aClassSubject.init("int");
- assertThat(firstInitSubject, isPresent());
- assertThat(
- firstInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
+ MethodSubject firstInitSubject = aClassSubject.init("int");
+ assertThat(firstInitSubject, isPresent());
+ assertThat(firstInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
- MethodSubject otherInitSubject =
- aClassSubject.init(changedClassSubject.getFinalName(), "int");
- assertThat(otherInitSubject, isPresent());
- assertThat(
- otherInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
+ MethodSubject otherInitSubject =
+ aClassSubject.init(changedClassSubject.getFinalName(), "int");
+ assertThat(otherInitSubject, isPresent());
+ assertThat(otherInitSubject, writesInstanceField(classIdFieldSubject.getDexField()));
- MethodSubject printSubject = aClassSubject.method("void", "print$bridge");
- assertThat(printSubject, isPresent());
- assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
+ MethodSubject printSubject = aClassSubject.method("void", "print$bridge");
+ assertThat(printSubject, isPresent());
+ assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
- assertThat(codeInspector.clazz(B.class), not(isPresent()));
-
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java
index 21c3486..b76442b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java
@@ -13,8 +13,8 @@
import org.junit.Test;
public class ConstructorMergingTest extends HorizontalClassMergingTestBase {
- public ConstructorMergingTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,23 +22,14 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("foo", "bar")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java
index 50da81e..0dd1f3e 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTrivialOverlapTest.java
@@ -21,9 +21,8 @@
public class ConstructorMergingTrivialOverlapTest extends HorizontalClassMergingTestBase {
- public ConstructorMergingTrivialOverlapTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorMergingTrivialOverlapTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -31,9 +30,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -41,7 +37,6 @@
.assertSuccessWithOutputLines("7", "42", "13", "print a", "print b")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
FieldSubject classIdFieldSubject =
@@ -66,12 +61,6 @@
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
assertThat(codeInspector.clazz(B.class), not(isPresent()));
-
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java
index 7891de2..30a84ca 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java
@@ -15,9 +15,8 @@
import org.junit.Test;
public class ConstructorMergingWithArgumentsTest extends HorizontalClassMergingTestBase {
- public ConstructorMergingWithArgumentsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ConstructorMergingWithArgumentsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,16 +24,12 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("foo hello", "bar world")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
@@ -42,11 +37,6 @@
MethodSubject initSubject = aClassSubject.init(String.class.getName(), "int");
assertThat(initSubject, isPresent());
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/DistinguishExceptionClassesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/DistinguishExceptionClassesTest.java
index 749ae58..e063a4b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/DistinguishExceptionClassesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/DistinguishExceptionClassesTest.java
@@ -11,9 +11,8 @@
import org.junit.Test;
public class DistinguishExceptionClassesTest extends HorizontalClassMergingTestBase {
- public DistinguishExceptionClassesTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public DistinguishExceptionClassesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -21,9 +20,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("test success")
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java
index 5d63188..d33b180 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -15,8 +15,8 @@
import org.junit.Test;
public class EmptyClassTest extends HorizontalClassMergingTestBase {
- public EmptyClassTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public EmptyClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,20 +24,16 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("a", "b: foo")
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldTypeMergedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldTypeMergedTest.java
index 58434a9..e688559 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldTypeMergedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldTypeMergedTest.java
@@ -4,10 +4,10 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isFieldOfArrayType;
import static com.android.tools.r8.utils.codeinspector.Matchers.isFieldOfType;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -19,8 +19,8 @@
import org.junit.Test;
public class FieldTypeMergedTest extends HorizontalClassMergingTestBase {
- public FieldTypeMergedTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public FieldTypeMergedTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -28,9 +28,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -40,28 +37,21 @@
codeInspector -> {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
ClassSubject cClassSubject = codeInspector.clazz(C.class);
assertThat(codeInspector.clazz(C.class), isPresent());
FieldSubject fieldSubject = cClassSubject.uniqueFieldWithName("fieldB");
assertThat(fieldSubject, isPresent());
- if (enableHorizontalClassMerging) {
- assertThat(
- fieldSubject, isFieldOfType(aClassSubject.getDexProgramClass().getType()));
- }
+ assertThat(fieldSubject, isFieldOfType(aClassSubject.getDexProgramClass().getType()));
fieldSubject = cClassSubject.uniqueFieldWithName("fieldArrayB");
assertThat(fieldSubject, isPresent());
assertTrue(fieldSubject.getDexField().type.isArrayType());
- if (enableHorizontalClassMerging) {
- assertThat(
- fieldSubject,
- isFieldOfArrayType(
- codeInspector, aClassSubject.getDexProgramClass().getType()));
- }
+ assertThat(
+ fieldSubject,
+ isFieldOfArrayType(codeInspector, aClassSubject.getDexProgramClass().getType()));
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldsWithDifferentAccessFlagsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldsWithDifferentAccessFlagsTest.java
index 58acdbf..7468ce5 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldsWithDifferentAccessFlagsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/FieldsWithDifferentAccessFlagsTest.java
@@ -14,9 +14,8 @@
public class FieldsWithDifferentAccessFlagsTest extends HorizontalClassMergingTestBase {
- public FieldsWithDifferentAccessFlagsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public FieldsWithDifferentAccessFlagsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,11 +23,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, HorizontallyMergedClassesInspector::assertNoClassesMerged)
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/GenericStaticFieldTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/GenericStaticFieldTest.java
index af72afe..e1248e1 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/GenericStaticFieldTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/GenericStaticFieldTest.java
@@ -9,8 +9,8 @@
import org.junit.Test;
public class GenericStaticFieldTest extends HorizontalClassMergingTestBase {
- public GenericStaticFieldTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public GenericStaticFieldTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -19,9 +19,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addKeepRules("-keepattributes Signatures")
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
// .addHorizontallyMergedClassesInspectorIf(
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
index 5b2dbe7..fa19056 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
@@ -6,29 +6,25 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
-import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.List;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public abstract class HorizontalClassMergingTestBase extends TestBase {
- protected final TestParameters parameters;
- protected final boolean enableHorizontalClassMerging;
- protected HorizontalClassMergingTestBase(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
+ protected final TestParameters parameters;
+
+ protected HorizontalClassMergingTestBase(TestParameters parameters) {
this.parameters = parameters;
- this.enableHorizontalClassMerging = enableHorizontalClassMerging;
}
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
protected ClassSubject getSynthesizedArgumentClassSubject(CodeInspector codeInspector) {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java
index 9dae7a2..08a3bd7 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java
@@ -4,17 +4,16 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.*;
import org.junit.Test;
public class IdenticalFieldMembersTest extends HorizontalClassMergingTestBase {
- public IdenticalFieldMembersTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public IdenticalFieldMembersTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,9 +21,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -33,8 +29,7 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java
index b069bb1..ef0cedf 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritInterfaceWithDefaultTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -18,9 +18,8 @@
public class InheritInterfaceWithDefaultTest extends HorizontalClassMergingTestBase {
- public InheritInterfaceWithDefaultTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public InheritInterfaceWithDefaultTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -29,22 +28,18 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.allowStdoutMessages()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(
"print interface", "print interface", "print interface", "print interface")
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritOverrideInterfaceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritOverrideInterfaceTest.java
index 8c7644d..8bea286 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritOverrideInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritOverrideInterfaceTest.java
@@ -13,9 +13,8 @@
import org.junit.Test;
public class InheritOverrideInterfaceTest extends HorizontalClassMergingTestBase {
- public InheritOverrideInterfaceTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public InheritOverrideInterfaceTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -23,14 +22,11 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("A", "B", "A")
.inspect(codeInspector -> {});
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritsFromLibraryClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritsFromLibraryClassTest.java
index 575c2cd..33a1909 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritsFromLibraryClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InheritsFromLibraryClassTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -19,9 +19,8 @@
import org.junit.Test;
public class InheritsFromLibraryClassTest extends HorizontalClassMergingTestBase {
- public InheritsFromLibraryClassTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public InheritsFromLibraryClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -29,9 +28,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -41,8 +37,7 @@
codeInspector -> {
assertThat(codeInspector.clazz(Parent.class), isPresent());
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
assertThat(codeInspector.clazz(C.class), isPresent());
});
}
@@ -74,7 +69,7 @@
}
@NeverClassInline
- public static class C extends ArrayList {
+ public static class C extends ArrayList<Object> {
public C() {}
public void fooB(B b) {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InnerOuterClassesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InnerOuterClassesTest.java
index 98e74e4..a6a93ad 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/InnerOuterClassesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InnerOuterClassesTest.java
@@ -12,8 +12,8 @@
import org.junit.Test;
public class InnerOuterClassesTest extends HorizontalClassMergingTestBase {
- public InnerOuterClassesTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public InnerOuterClassesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -21,9 +21,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.addKeepAttributes("InnerClasses", "EnclosingMethod")
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InstantiatedAndUninstantiatedClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InstantiatedAndUninstantiatedClassMergingTest.java
index 59e77dd..d6b6643 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/InstantiatedAndUninstantiatedClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InstantiatedAndUninstantiatedClassMergingTest.java
@@ -16,9 +16,8 @@
public class InstantiatedAndUninstantiatedClassMergingTest extends HorizontalClassMergingTestBase {
- public InstantiatedAndUninstantiatedClassMergingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public InstantiatedAndUninstantiatedClassMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -35,9 +34,6 @@
testBuilder
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.addHorizontallyMergedClassesInspector(
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/JavaLambdaMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/JavaLambdaMergingTest.java
index f7aacb5..6f96433 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/JavaLambdaMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/JavaLambdaMergingTest.java
@@ -18,8 +18,8 @@
public class JavaLambdaMergingTest extends HorizontalClassMergingTestBase {
- public JavaLambdaMergingTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public JavaLambdaMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -27,11 +27,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging && parameters.isDexRuntime(),
+ parameters.isDexRuntime(),
inspector -> {
Set<DexType> lambdaSources =
inspector.getSources().stream()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/LargeConstructorsMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/LargeConstructorsMergingTest.java
index a553abe..00b1f38 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/LargeConstructorsMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/LargeConstructorsMergingTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -15,9 +15,8 @@
import org.junit.Test;
public class LargeConstructorsMergingTest extends HorizontalClassMergingTestBase {
- public LargeConstructorsMergingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public LargeConstructorsMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,14 +24,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addOptionsModification(options -> options.testing.verificationSizeLimitInBytesOverride = 4)
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
inspector.assertMergedInto(B.class, A.class).assertMergedInto(C.class, A.class))
.run(parameters.getRuntime(), Main.class)
@@ -41,15 +36,11 @@
codeInspector -> {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
- assertThat(
- codeInspector.clazz(C.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
+ assertThat(codeInspector.clazz(C.class), isAbsent());
- if (enableHorizontalClassMerging) {
- // There should be three constructors on class A after merging.
- assertEquals(3, aClassSubject.allMethods().size());
- }
+ // There should be three constructors on class A after merging.
+ assertEquals(3, aClassSubject.allMethods().size());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergeNonFinalAndFinalClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergeNonFinalAndFinalClassTest.java
index c8a36b6..1285ea1 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergeNonFinalAndFinalClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergeNonFinalAndFinalClassTest.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isFinal;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
+import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -14,9 +14,8 @@
import org.junit.Test;
public class MergeNonFinalAndFinalClassTest extends HorizontalClassMergingTestBase {
- public MergeNonFinalAndFinalClassTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergeNonFinalAndFinalClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,19 +23,13 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
.compile()
- .inspect(
- inspector ->
- assertThat(
- inspector.clazz(A.class), notIf(isFinal(), enableHorizontalClassMerging)))
+ .inspect(inspector -> assertThat(inspector.clazz(A.class), not(isFinal())))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("a", "b", "b", "c");
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergePackagePrivateWithPublicClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergePackagePrivateWithPublicClassTest.java
index 04d69b1d..409ea48 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergePackagePrivateWithPublicClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergePackagePrivateWithPublicClassTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestParameters;
@@ -14,9 +14,8 @@
public class MergePackagePrivateWithPublicClassTest extends HorizontalClassMergingTestBase {
- public MergePackagePrivateWithPublicClassTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergePackagePrivateWithPublicClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,9 +25,6 @@
.addProgramClasses(
PackagePrivateClassRunner.class, PackagePrivateClassRunner.getPrivateClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -39,8 +35,7 @@
codeInspector -> {
assertThat(codeInspector.clazz(PackagePrivateClassRunner.class), isPresent());
assertThat(
- codeInspector.clazz(PackagePrivateClassRunner.getPrivateClass()),
- notIf(isPresent(), enableHorizontalClassMerging));
+ codeInspector.clazz(PackagePrivateClassRunner.getPrivateClass()), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
index f913560..5484fd8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
@@ -21,9 +21,8 @@
public class MergedConstructorForwardingTest extends HorizontalClassMergingTestBase {
- public MergedConstructorForwardingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergedConstructorForwardingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -31,9 +30,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -41,7 +37,6 @@
.assertSuccessWithOutputLines("42", "13", "21", "39", "print a", "print b")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
ClassSubject aClassSubject = codeInspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
FieldSubject classIdFieldSubject =
@@ -63,12 +58,6 @@
assertThat(printSubject, readsInstanceField(classIdFieldSubject.getDexField()));
assertThat(codeInspector.clazz(B.class), not(isPresent()));
-
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorStackTraceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorStackTraceTest.java
index a11a7d6..e785238 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorStackTraceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorStackTraceTest.java
@@ -22,9 +22,8 @@
public StackTrace expectedStackTrace;
- public MergedConstructorStackTraceTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergedConstructorStackTraceTest(TestParameters parameters) {
+ super(parameters);
}
@Before
@@ -45,9 +44,6 @@
.addKeepMainRule(Main.class)
.addKeepAttributeLineNumberTable()
.addKeepAttributeSourceFile()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNoVerticalClassMergingAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -56,7 +52,6 @@
.inspectStackTrace(
(stackTrace, codeInspector) -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- if (enableHorizontalClassMerging) {
StackTrace expectedStackTraceWithMergedConstructor =
StackTrace.builder()
.add(expectedStackTrace)
@@ -73,10 +68,6 @@
.build();
assertThat(stackTrace, isSame(expectedStackTraceWithMergedConstructor));
assertThat(codeInspector.clazz(B.class), not(isPresent()));
- } else {
- assertThat(stackTrace, isSame(expectedStackTrace));
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStackTraceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStackTraceTest.java
index 8c9d11d..0375885 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStackTraceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStackTraceTest.java
@@ -5,8 +5,8 @@
package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.naming.retrace.StackTrace.isSame;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -19,9 +19,8 @@
import org.junit.Test;
public class MergedVirtualMethodStackTraceTest extends HorizontalClassMergingTestBase {
- public MergedVirtualMethodStackTraceTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergedVirtualMethodStackTraceTest(TestParameters parameters) {
+ super(parameters);
}
public StackTrace expectedStackTrace;
@@ -45,38 +44,30 @@
.addKeepAttributeLineNumberTable()
.addKeepAttributeSourceFile()
.addDontWarn(C.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertMergedInto(Program.B.class, Program.A.class))
.run(parameters.getRuntime(), Program.Main.class)
.inspectStackTrace(
(stackTrace, codeInspector) -> {
assertThat(codeInspector.clazz(Program.A.class), isPresent());
- assertThat(
- codeInspector.clazz(Program.B.class),
- notIf(isPresent(), enableHorizontalClassMerging));
- if (enableHorizontalClassMerging) {
- StackTrace expectedStackTraceWithMergedMethod =
- StackTrace.builder()
- .add(expectedStackTrace)
- .add(
- 1,
- StackTraceLine.builder()
- .setClassName(Program.A.class.getTypeName())
- .setMethodName("foo$bridge")
- .setFileName("Program.java")
- .setFileName(getClass().getSimpleName() + ".java")
- .setLineNumber(stackTrace.get(1).lineNumber)
- .build())
- .build();
- assertThat(stackTrace, isSame(expectedStackTraceWithMergedMethod));
- }
+ assertThat(codeInspector.clazz(Program.B.class), isAbsent());
+ StackTrace expectedStackTraceWithMergedMethod =
+ StackTrace.builder()
+ .add(expectedStackTrace)
+ .add(
+ 1,
+ StackTraceLine.builder()
+ .setClassName(Program.A.class.getTypeName())
+ .setMethodName("foo$bridge")
+ .setFileName("Program.java")
+ .setFileName(getClass().getSimpleName() + ".java")
+ .setLineNumber(stackTrace.get(1).lineNumber)
+ .build())
+ .build();
+ assertThat(stackTrace, isSame(expectedStackTraceWithMergedMethod));
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStaticizerTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStaticizerTest.java
index e7eda20..3ffb5a2 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedVirtualMethodStaticizerTest.java
@@ -10,9 +10,8 @@
import org.junit.Test;
public class MergedVirtualMethodStaticizerTest extends HorizontalClassMergingTestBase {
- public MergedVirtualMethodStaticizerTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergedVirtualMethodStaticizerTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -20,14 +19,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(Program.class)
.addKeepClassAndMembersRules(Program.Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertMergedInto(Program.B.class, Program.A.class))
.run(parameters.getRuntime(), Program.Main.class)
.assertSuccessWithOutputLines("A::foo", "Staticized::foo", "B::foo");
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergingProducesFieldCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergingProducesFieldCollisionTest.java
index 13cc54f..06242c1 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergingProducesFieldCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergingProducesFieldCollisionTest.java
@@ -4,22 +4,20 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import org.junit.Test;
public class MergingProducesFieldCollisionTest extends HorizontalClassMergingTestBase {
- public MergingProducesFieldCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MergingProducesFieldCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -30,9 +28,6 @@
.addKeepMainRule(Main.class)
.addProgramClassFileData(transformedC)
.addProgramClasses(Parent.class, A.class, B.class, Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -46,16 +41,13 @@
assertThat(aClassSubject, isPresent());
ClassSubject bClassSubject = codeInspector.clazz(B.class);
- assertThat(bClassSubject, notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(bClassSubject, isAbsent());
ClassSubject cClassSubject = codeInspector.clazz(C.class);
assertThat(cClassSubject, isPresent());
- if (enableHorizontalClassMerging) {
- assertEquals(
- cClassSubject.allFields().get(0).type(),
- cClassSubject.allFields().get(1).type());
- }
+ assertEquals(
+ cClassSubject.allFields().get(0).type(), cClassSubject.allFields().get(1).type());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MinimizeFieldCastsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MinimizeFieldCastsTest.java
index 90ae326..319e1c0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/MinimizeFieldCastsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MinimizeFieldCastsTest.java
@@ -12,8 +12,8 @@
public class MinimizeFieldCastsTest extends HorizontalClassMergingTestBase {
- public MinimizeFieldCastsTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public MinimizeFieldCastsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -21,15 +21,11 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
// Two merge groups are expected since we attempt to merge classes in a way that
// avoids merging fields with different types unless strictly required for merging.
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java
index a043e68..215ce7a 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java
@@ -4,24 +4,23 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPrivate;
import static com.android.tools.r8.utils.codeinspector.Matchers.isStatic;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.Jdk9TestUtils;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.classmerging.horizontal.NestClassTest.R.horizontalclassmerging.BasicNestHostHorizontalClassMerging;
import com.android.tools.r8.classmerging.horizontal.NestClassTest.R.horizontalclassmerging.BasicNestHostHorizontalClassMerging2;
-import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesClass;
import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesJava11RootPackage;
import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesPackage;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.util.List;
import org.junit.Test;
import org.junit.runners.Parameterized;
@@ -42,15 +41,13 @@
}
}
- public NestClassTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NestClassTest(TestParameters parameters) {
+ super(parameters);
}
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withCfRuntimesStartingFromIncluding(CfVm.JDK11).build(),
- BooleanUtils.values());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withCfRuntimesStartingFromIncluding(CfVm.JDK11).build();
}
@Test
@@ -59,9 +56,6 @@
.addKeepMainRule(examplesTypeName(BasicNestHostHorizontalClassMerging.class))
.addExamplesProgramFiles(R.class)
.applyIf(parameters.isCfRuntime(), Jdk9TestUtils.addJdk9LibraryFiles(temp))
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.compile()
@@ -98,11 +92,11 @@
assertThat(
codeInspector.clazz(
examplesTypeName(BasicNestHostHorizontalClassMerging.B.class)),
- notIf(isPresent(), enableHorizontalClassMerging));
+ isAbsent());
assertThat(
codeInspector.clazz(
examplesTypeName(BasicNestHostHorizontalClassMerging2.B.class)),
- notIf(isPresent(), enableHorizontalClassMerging));
+ isAbsent());
// TODO(b/165517236): Explicitly check 1.B is merged into 1.A, and 2.B into 2.A.
});
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoAbstractClassesWithNonAbstractClassesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoAbstractClassesWithNonAbstractClassesTest.java
index 5566f45..4ebbd51 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoAbstractClassesWithNonAbstractClassesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoAbstractClassesWithNonAbstractClassesTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -15,9 +15,8 @@
import org.junit.Test;
public class NoAbstractClassesWithNonAbstractClassesTest extends HorizontalClassMergingTestBase {
- public NoAbstractClassesWithNonAbstractClassesTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NoAbstractClassesWithNonAbstractClassesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +24,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -39,8 +35,7 @@
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), isPresent());
assertThat(codeInspector.clazz(C.class), isPresent());
- assertThat(
- codeInspector.clazz(D.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(D.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java
index 441934e..385a3fe 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoClassesOrMembersWithAnnotationsTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -20,9 +20,9 @@
import org.junit.Test;
public class NoClassesOrMembersWithAnnotationsTest extends HorizontalClassMergingTestBase {
- public NoClassesOrMembersWithAnnotationsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+
+ public NoClassesOrMembersWithAnnotationsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -31,11 +31,7 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertIsCompleteMergeGroup(A.class, C.class))
.enableNeverClassInliningAnnotations()
.enableInliningAnnotations()
@@ -49,8 +45,7 @@
assertThat(codeInspector.clazz(MethodAnnotation.class), isPresent());
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), isPresent());
- assertThat(
- codeInspector.clazz(C.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(C.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoHorizontalClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoHorizontalClassMergingTest.java
index 5c0e207..1382648 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NoHorizontalClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NoHorizontalClassMergingTest.java
@@ -13,9 +13,8 @@
import org.junit.Test;
public class NoHorizontalClassMergingTest extends HorizontalClassMergingTestBase {
- public NoHorizontalClassMergingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NoHorizontalClassMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -23,9 +22,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNoHorizontalClassMergingAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -33,13 +29,8 @@
.assertSuccessWithOutputLines("a", "b")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), isPresent());
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodTest.java
index d73ffcf..110f7f6 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonFinalOverrideOfFinalMethodTest.java
@@ -12,24 +12,21 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.util.List;
import org.junit.Test;
import org.junit.runners.Parameterized;
public class NonFinalOverrideOfFinalMethodTest extends HorizontalClassMergingTestBase {
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.trueValues());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public NonFinalOverrideOfFinalMethodTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NonFinalOverrideOfFinalMethodTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -37,15 +34,12 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.compile()
.inspect(
inspector -> {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessOnMergedClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessOnMergedClassTest.java
index 029035e..a54102f 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessOnMergedClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessOnMergedClassTest.java
@@ -14,9 +14,8 @@
@RunWith(Parameterized.class)
public class NonReboundFieldAccessOnMergedClassTest extends HorizontalClassMergingTestBase {
- public NonReboundFieldAccessOnMergedClassTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NonReboundFieldAccessOnMergedClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,11 +24,8 @@
.addInnerClasses(getClass())
.addInnerClasses(NonReboundFieldAccessOnMergedClassTestClasses.class)
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(D.class, C.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(D.class, C.class))
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessWithMergedTypeTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessWithMergedTypeTest.java
index 03b99e0..4b17a09 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessWithMergedTypeTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NonReboundFieldAccessWithMergedTypeTest.java
@@ -14,9 +14,8 @@
@RunWith(Parameterized.class)
public class NonReboundFieldAccessWithMergedTypeTest extends HorizontalClassMergingTestBase {
- public NonReboundFieldAccessWithMergedTypeTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NonReboundFieldAccessWithMergedTypeTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,11 +24,7 @@
.addInnerClasses(getClass())
.addInnerClasses(NonReboundFieldAccessWithMergedTypeTestClasses.class)
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector -> inspector.assertMergedInto(WorldGreeting.class, HelloGreeting.class))
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java
index c97e384..2927247 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java
@@ -14,9 +14,8 @@
public class OverlappingConstructorsTest extends HorizontalClassMergingTestBase {
- public OverlappingConstructorsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public OverlappingConstructorsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,24 +23,14 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
assertThat(codeInspector.clazz(C.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- assertThat(codeInspector.clazz(C.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMemberAccessTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMemberAccessTest.java
index 2732240..820af37 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMemberAccessTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMemberAccessTest.java
@@ -15,9 +15,8 @@
import org.junit.Test;
public class PackagePrivateMemberAccessTest extends HorizontalClassMergingTestBase {
- public PackagePrivateMemberAccessTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PackagePrivateMemberAccessTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -27,9 +26,6 @@
.addProgramClasses(A.class)
.addProgramClasses(B.class)
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.allowAccessModification(false)
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
@@ -38,16 +34,9 @@
.assertSuccessWithOutputLines("foo", "B", "bar", "5", "foobar")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
assertThat(codeInspector.clazz(C.class), isPresent());
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- assertThat(codeInspector.clazz(C.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMembersAccessedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMembersAccessedTest.java
index 4d7c0c4..bb756d0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMembersAccessedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PackagePrivateMembersAccessedTest.java
@@ -14,9 +14,8 @@
import org.junit.Test;
public class PackagePrivateMembersAccessedTest extends HorizontalClassMergingTestBase {
- public PackagePrivateMembersAccessedTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PackagePrivateMembersAccessedTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,9 +25,6 @@
.addProgramClasses(C.class)
.addProgramClasses(D.class)
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.allowAccessModification(false)
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberReferenceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberReferenceTest.java
index 2f01f90..41694f6 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberReferenceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberReferenceTest.java
@@ -18,18 +18,14 @@
import org.junit.Test;
public class PinnedClassMemberReferenceTest extends HorizontalClassMergingTestBase {
- public PinnedClassMemberReferenceTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PinnedClassMemberReferenceTest(TestParameters parameters) {
+ super(parameters);
}
private R8FullTestBuilder testCommon() throws Exception {
return testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.noMinification()
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
@@ -46,7 +42,6 @@
@Test
public void testWithoutKeepRules() throws Exception {
// This is just a small check ensure that without the keep rules the classes are merged.
- assumeTrue(enableHorizontalClassMerging);
assumeTrue(parameters.isCfRuntime());
runAndAssertOutput(testCommon())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberTest.java
index 1e09a5a..ca080ae 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassMemberTest.java
@@ -12,8 +12,8 @@
import org.junit.Test;
public class PinnedClassMemberTest extends HorizontalClassMergingTestBase {
- public PinnedClassMemberTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PinnedClassMemberTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,9 +22,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addKeepRules("-keepclassmembers class " + B.class.getTypeName() + " { void foo(); }")
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassTest.java
index 0ba06e6..af092cc 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PinnedClassTest.java
@@ -12,8 +12,8 @@
import org.junit.Test;
public class PinnedClassTest extends HorizontalClassMergingTestBase {
- public PinnedClassTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PinnedClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,9 +22,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addKeepClassRules(B.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexListTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexListTest.java
index e3e1b85..2aeacb8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexListTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexListTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
@@ -12,48 +13,46 @@
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.classmerging.horizontal.EmptyClassTest.A;
-import com.android.tools.r8.classmerging.horizontal.EmptyClassTest.B;
-import com.android.tools.r8.classmerging.horizontal.EmptyClassTest.Main;
-import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.nio.file.Path;
-import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class PreventMergeMainDexListTest extends HorizontalClassMergingTestBase {
- public PreventMergeMainDexListTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PreventMergeMainDexListTest(TestParameters parameters) {
+ super(parameters);
}
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters()
- .withDexRuntimes()
- .withApiLevelsEndingAtExcluding(apiLevelWithNativeMultiDexSupport())
- .build(),
- BooleanUtils.values());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters()
+ .withDexRuntimes()
+ .withApiLevelsEndingAtExcluding(apiLevelWithNativeMultiDexSupport())
+ .build();
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
+ // Ensure the main-dex-rules variant of this test (PreventMergeMainDexTracingTest) is sufficient.
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepClassAndMembersRules(Main.class)
.addMainDexListClasses(A.class, Main.class)
- .addOptionsModification(
- options -> {
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging);
- options.minimalMainDex = true;
- })
+ .addOptionsModification(options -> options.minimalMainDex = true)
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .compile()
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)))
.apply(this::checkCompileResult)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("main dex");
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexTracingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexTracingTest.java
index 13d8a62..de0bd57 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexTracingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PreventMergeMainDexTracingTest.java
@@ -13,29 +13,25 @@
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.nio.file.Path;
-import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class PreventMergeMainDexTracingTest extends HorizontalClassMergingTestBase {
- public PreventMergeMainDexTracingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PreventMergeMainDexTracingTest(TestParameters parameters) {
+ super(parameters);
}
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters()
- .withDexRuntimes()
- .withApiLevelsEndingAtExcluding(apiLevelWithNativeMultiDexSupport())
- .build(),
- BooleanUtils.values());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters()
+ .withDexRuntimes()
+ .withApiLevelsEndingAtExcluding(apiLevelWithNativeMultiDexSupport())
+ .build();
}
@Test
@@ -44,12 +40,8 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addKeepClassAndMembersRules(Other.class)
- .addMainDexClassRules(Main.class)
- .addOptionsModification(
- options -> {
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging);
- options.minimalMainDex = true;
- })
+ .addMainDexKeepClassRules(Main.class)
+ .addOptionsModification(options -> options.minimalMainDex = true)
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndInterfaceMethodCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndInterfaceMethodCollisionTest.java
index 4553469..f440689 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndInterfaceMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndInterfaceMethodCollisionTest.java
@@ -14,9 +14,8 @@
public class PrivateAndInterfaceMethodCollisionTest extends HorizontalClassMergingTestBase {
- public PrivateAndInterfaceMethodCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PrivateAndInterfaceMethodCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,9 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addHorizontallyMergedClassesInspector(
HorizontallyMergedClassesInspector::assertNoClassesMerged)
.enableInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndStaticMethodCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndStaticMethodCollisionTest.java
index 3c7b799..a646bf3 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndStaticMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/PrivateAndStaticMethodCollisionTest.java
@@ -11,9 +11,8 @@
public class PrivateAndStaticMethodCollisionTest extends HorizontalClassMergingTestBase {
- public PrivateAndStaticMethodCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public PrivateAndStaticMethodCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -21,11 +20,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ReferencedInAnnotationTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ReferencedInAnnotationTest.java
index 385d782..08f1f0d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ReferencedInAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ReferencedInAnnotationTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -26,9 +26,8 @@
public class ReferencedInAnnotationTest extends HorizontalClassMergingTestBase {
- public ReferencedInAnnotationTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ReferencedInAnnotationTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -37,9 +36,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
.addKeepClassAndMembersRules(Annotation.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addKeepRuntimeVisibleAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -58,7 +54,7 @@
// B should have been merged into A if horizontal class merging is enabled.
ClassSubject bClassSubject = inspector.clazz(B.class);
- assertThat(bClassSubject, notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(bClassSubject, isAbsent());
// The annotation on TestClass should now refer to A instead of B.
AnnotationSubject annotationSubject =
@@ -72,11 +68,7 @@
assertTrue(annotationElementValue.isDexValueType());
DexType annotationElementValueType = annotationElementValue.asDexValueType().getValue();
- assertEquals(
- (enableHorizontalClassMerging ? aClassSubject : bClassSubject)
- .getDexProgramClass()
- .getType(),
- annotationElementValueType);
+ assertEquals(aClassSubject.getDexProgramClass().getType(), annotationElementValueType);
}
@Annotation(B.class)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapFieldTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapFieldTest.java
index 168d6ee..3abb15d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapFieldTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapFieldTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -14,8 +14,8 @@
import org.junit.Test;
public class RemapFieldTest extends HorizontalClassMergingTestBase {
- public RemapFieldTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public RemapFieldTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -23,14 +23,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
inspector.assertMergedInto(B.class, A.class).assertMergedInto(D.class, C.class))
.run(parameters.getRuntime(), Main.class)
@@ -38,11 +34,9 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
assertThat(codeInspector.clazz(C.class), isPresent());
- assertThat(
- codeInspector.clazz(D.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(D.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java
index c640ffc..71e3e74 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java
@@ -14,8 +14,8 @@
import org.junit.Test;
public class RemapMethodTest extends HorizontalClassMergingTestBase {
- public RemapMethodTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public RemapMethodTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -23,9 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -36,14 +33,8 @@
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(C.class), isPresent());
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(B.class), not(isPresent()));
assertThat(codeInspector.clazz(D.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(B.class), isPresent());
- assertThat(codeInspector.clazz(D.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderParentTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderParentTest.java
index 5eab9c9..311d835 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderParentTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderParentTest.java
@@ -18,8 +18,8 @@
import org.junit.Test;
public class ServiceLoaderParentTest extends HorizontalClassMergingTestBase {
- public ServiceLoaderParentTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ServiceLoaderParentTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -37,9 +37,6 @@
"META-INF/services/" + A.class.getTypeName(),
Origin.unknown()))
.enableNoVerticalClassMergingAnnotations()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccess()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderTest.java
index f9ae4bd..0b4a848 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ServiceLoaderTest.java
@@ -17,8 +17,8 @@
import org.junit.Test;
public class ServiceLoaderTest extends HorizontalClassMergingTestBase {
- public ServiceLoaderTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public ServiceLoaderTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -35,9 +35,6 @@
StringUtils.lines(serviceImplementations).getBytes(),
"META-INF/services/" + A.class.getTypeName(),
Origin.unknown()))
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccess()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndInterfaceMethodCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndInterfaceMethodCollisionTest.java
index e76dd447..48844ff 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndInterfaceMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndInterfaceMethodCollisionTest.java
@@ -14,9 +14,8 @@
public class StaticAndInterfaceMethodCollisionTest extends HorizontalClassMergingTestBase {
- public StaticAndInterfaceMethodCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public StaticAndInterfaceMethodCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,9 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.addHorizontallyMergedClassesInspector(
HorizontallyMergedClassesInspector::assertNoClassesMerged)
.enableInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndVirtualMethodCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndVirtualMethodCollisionTest.java
index 35a15e5..993dd65 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndVirtualMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/StaticAndVirtualMethodCollisionTest.java
@@ -12,9 +12,8 @@
public class StaticAndVirtualMethodCollisionTest extends HorizontalClassMergingTestBase {
- public StaticAndVirtualMethodCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public StaticAndVirtualMethodCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,11 +21,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, inspector -> inspector.assertMergedInto(B.class, A.class))
+ .addHorizontallyMergedClassesInspector(
+ inspector -> inspector.assertMergedInto(B.class, A.class))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java
index 762824f..4d793a4 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/StrictMethodMergingTest.java
@@ -12,23 +12,21 @@
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.util.List;
import org.junit.Test;
import org.junit.runners.Parameterized;
public class StrictMethodMergingTest extends HorizontalClassMergingTestBase {
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.trueValues());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public StrictMethodMergingTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public StrictMethodMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -36,14 +34,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
inspector.assertMergedInto(B.class, A.class).assertMergedInto(D.class, C.class))
.compile()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/SuperConstructorCallsVirtualMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/SuperConstructorCallsVirtualMethodTest.java
index ecbd84b..821d644 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/SuperConstructorCallsVirtualMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/SuperConstructorCallsVirtualMethodTest.java
@@ -14,9 +14,8 @@
import org.junit.Test;
public class SuperConstructorCallsVirtualMethodTest extends HorizontalClassMergingTestBase {
- public SuperConstructorCallsVirtualMethodTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public SuperConstructorCallsVirtualMethodTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,9 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -34,16 +30,9 @@
.assertSuccessWithOutputLines("5", "foo hello", "B", "bar world", "5", "B")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(Parent.class), isPresent());
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(Parent.class), isPresent());
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedClassesTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedClassesTest.java
index 6f458b7..a88c32b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedClassesTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedClassesTest.java
@@ -15,8 +15,8 @@
import org.junit.Test;
public class SynchronizedClassesTest extends HorizontalClassMergingTestBase {
- public SynchronizedClassesTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public SynchronizedClassesTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,10 +24,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options -> {
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging);
- })
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -38,7 +34,6 @@
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), isPresent());
- if (enableHorizontalClassMerging) {
// C has been merged into A.
assertThat(codeInspector.clazz(C.class), not(isPresent()));
assertThat(codeInspector.clazz(A.class).init("long"), isPresent());
@@ -47,10 +42,6 @@
assertThat(codeInspector.clazz(D.class), not(isPresent()));
ClassSubject bClassSubject = codeInspector.clazz(B.class);
assertThat(bClassSubject.init("boolean"), isPresent());
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java
index 8d802c4..4811a41 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/SynchronizedMethodMergingTest.java
@@ -12,24 +12,21 @@
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.util.List;
import org.junit.Test;
import org.junit.runners.Parameterized;
public class SynchronizedMethodMergingTest extends HorizontalClassMergingTestBase {
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.trueValues());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public SynchronizedMethodMergingTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public SynchronizedMethodMergingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -37,14 +34,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging,
+ .addHorizontallyMergedClassesInspector(
inspector ->
inspector.assertMergedInto(B.class, A.class).assertMergedInto(D.class, C.class))
.compile()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java
index 6567764..eb3fe19 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java
@@ -14,9 +14,8 @@
import org.junit.Test;
public class SyntheticConstructorArgumentsMerged extends HorizontalClassMergingTestBase {
- public SyntheticConstructorArgumentsMerged(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public SyntheticConstructorArgumentsMerged(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,10 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options -> {
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging);
- })
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -36,14 +31,8 @@
.assertSuccessWithOutputLines("5", "42")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerCollisionTest.java
index 97e41db..2b56278 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerCollisionTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -16,8 +16,8 @@
import org.junit.Test;
public class TreeFixerCollisionTest extends HorizontalClassMergingTestBase {
- public TreeFixerCollisionTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public TreeFixerCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +25,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -39,13 +36,11 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
assertThat(codeInspector.clazz(Group2.class), isPresent());
assertThat(codeInspector.clazz(C.class), isPresent());
assertThat(codeInspector.clazz(D.class), isPresent());
- assertThat(
- codeInspector.clazz(E.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(E.class), isAbsent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerConstructorCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerConstructorCollisionTest.java
index 5239543..c5dff9d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerConstructorCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerConstructorCollisionTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -15,9 +15,8 @@
import org.junit.Test;
public class TreeFixerConstructorCollisionTest extends HorizontalClassMergingTestBase {
- public TreeFixerConstructorCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public TreeFixerConstructorCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +24,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
@@ -43,8 +39,7 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
assertThat(codeInspector.clazz(C.class), isPresent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java
index dbc83c8..fb7e05e 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -22,9 +22,8 @@
* changed.
*/
public class TreeFixerInterfaceCollisionTest extends HorizontalClassMergingTestBase {
- public TreeFixerInterfaceCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public TreeFixerInterfaceCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -33,9 +32,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.noMinification()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -46,15 +42,12 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
ClassSubject parentClassSubject = codeInspector.clazz(Parent.class);
assertThat(parentClassSubject, isPresent());
- if (enableHorizontalClassMerging) {
- // Parent#foo is renamed to Parent#foo1 to prevent collision.
- assertThat(parentClassSubject.uniqueMethodWithName("foo$1"), isPresent());
- }
+ // Parent#foo is renamed to Parent#foo1 to prevent collision.
+ assertThat(parentClassSubject.uniqueMethodWithName("foo$1"), isPresent());
ClassSubject cClassSubject = codeInspector.clazz(C.class);
assertThat(cClassSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java
index 169a59b..4dfb6df 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -22,9 +22,8 @@
* changed.
*/
public class TreeFixerInterfaceFixedCollisionTest extends HorizontalClassMergingTestBase {
- public TreeFixerInterfaceFixedCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public TreeFixerInterfaceFixedCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -33,9 +32,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.noMinification()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -46,15 +42,12 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
ClassSubject parentClassSubject = codeInspector.clazz(Parent.class);
assertThat(parentClassSubject, isPresent());
- if (enableHorizontalClassMerging) {
- // Parent#foo is renamed to Parent#foo1 to prevent collision.
- assertThat(parentClassSubject.uniqueMethodWithFinalName("foo$1"), isPresent());
- }
+ // Parent#foo is renamed to Parent#foo1 to prevent collision.
+ assertThat(parentClassSubject.uniqueMethodWithFinalName("foo$1"), isPresent());
ClassSubject cClassSubject = codeInspector.clazz(C.class);
assertThat(cClassSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceImplementedByParentTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceImplementedByParentTest.java
index afee32c..65b57aa 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceImplementedByParentTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceImplementedByParentTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -22,9 +22,8 @@
* changed.
*/
public class TreeFixerInterfaceImplementedByParentTest extends HorizontalClassMergingTestBase {
- public TreeFixerInterfaceImplementedByParentTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public TreeFixerInterfaceImplementedByParentTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -33,9 +32,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.noMinification()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -46,17 +42,14 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
ClassSubject parentClassSubject = codeInspector.clazz(Parent.class);
assertThat(parentClassSubject, isPresent());
// Parent #foo(A) is kept as is.
- if (enableHorizontalClassMerging) {
- // Parent#foo(B) is renamed to Parent#foo1 to prevent collision.
- assertThat(parentClassSubject.uniqueMethodWithFinalName("foo"), isPresent());
- assertThat(parentClassSubject.uniqueMethodWithFinalName("foo$1"), isPresent());
- }
+ // Parent#foo(B) is renamed to Parent#foo1 to prevent collision.
+ assertThat(parentClassSubject.uniqueMethodWithFinalName("foo"), isPresent());
+ assertThat(parentClassSubject.uniqueMethodWithFinalName("foo$1"), isPresent());
assertThat(codeInspector.clazz(C.class), isPresent());
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerSubClassCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerSubClassCollisionTest.java
index b68f291..5e8b88d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerSubClassCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerSubClassCollisionTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -17,9 +17,8 @@
import org.junit.Test;
public class TreeFixerSubClassCollisionTest extends HorizontalClassMergingTestBase {
- public TreeFixerSubClassCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public TreeFixerSubClassCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -28,9 +27,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.noMinification()
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -42,24 +38,18 @@
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), isAbsent());
ClassSubject cClassSubject = codeInspector.clazz(C.class);
assertThat(cClassSubject, isPresent());
// C#foo(B) is renamed to C#foo$1(A).
- if (enableHorizontalClassMerging) {
- assertThat(cClassSubject.uniqueMethodWithFinalName("foo"), isPresent());
- assertThat(cClassSubject.uniqueMethodWithFinalName("foo$1"), isPresent());
- }
+ assertThat(cClassSubject.uniqueMethodWithFinalName("foo"), isPresent());
+ assertThat(cClassSubject.uniqueMethodWithFinalName("foo$1"), isPresent());
ClassSubject dClassSubject = codeInspector.clazz(D.class);
assertThat(dClassSubject, isPresent());
// D#foo$1(B) is renamed to D#foo$2(A).
- assertThat(
- dClassSubject.uniqueMethodWithFinalName(
- enableHorizontalClassMerging ? "foo$1$1" : "foo$1"),
- isPresent());
+ assertThat(dClassSubject.uniqueMethodWithFinalName("foo$1$1"), isPresent());
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java
index b1c0b4a..db15d9c 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
@@ -17,9 +16,8 @@
public class VerticalMergingPreoptimizedTest extends HorizontalClassMergingTestBase {
- public VerticalMergingPreoptimizedTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public VerticalMergingPreoptimizedTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -27,9 +25,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
@@ -42,8 +37,7 @@
assertThat(codeInspector.clazz(Parent.class), not(isPresent()));
assertThat(codeInspector.clazz(Changed.class), isPresent());
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(
- codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByCheckCastTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByCheckCastTest.java
index eba6de8..0c13090 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByCheckCastTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByCheckCastTest.java
@@ -12,9 +12,8 @@
public class VerticallyMergedClassDistinguishedByCheckCastTest
extends HorizontalClassMergingTestBase {
- public VerticallyMergedClassDistinguishedByCheckCastTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public VerticallyMergedClassDistinguishedByCheckCastTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,9 +21,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByInstanceOfTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByInstanceOfTest.java
index 47994ef..a7a9f96 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByInstanceOfTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassDistinguishedByInstanceOfTest.java
@@ -12,9 +12,8 @@
public class VerticallyMergedClassDistinguishedByInstanceOfTest
extends HorizontalClassMergingTestBase {
- public VerticallyMergedClassDistinguishedByInstanceOfTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public VerticallyMergedClassDistinguishedByInstanceOfTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,9 +21,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassTest.java
index abd38f5..ab48235 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticallyMergedClassTest.java
@@ -15,9 +15,8 @@
import org.junit.Test;
public class VerticallyMergedClassTest extends HorizontalClassMergingTestBase {
- public VerticallyMergedClassTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public VerticallyMergedClassTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +24,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableNoHorizontalClassMergingAnnotations()
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfFinalAndNonFinalMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfFinalAndNonFinalMethodTest.java
index 6399f3e..0c51c89 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfFinalAndNonFinalMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfFinalAndNonFinalMethodTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.classmerging.horizontal;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
@@ -17,9 +17,8 @@
public class VirtualMethodMergingOfFinalAndNonFinalMethodTest
extends HorizontalClassMergingTestBase {
- public VirtualMethodMergingOfFinalAndNonFinalMethodTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public VirtualMethodMergingOfFinalAndNonFinalMethodTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -27,9 +26,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -38,8 +34,7 @@
.inspect(
inspector -> {
assertThat(inspector.clazz(A.class), isPresent());
- assertThat(
- inspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(inspector.clazz(B.class), isAbsent());
assertThat(inspector.clazz(C.class), isPresent());
})
.run(parameters.getRuntime(), TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfPublicizedMethodsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfPublicizedMethodsTest.java
index 5e23840..d3665e0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfPublicizedMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodMergingOfPublicizedMethodsTest.java
@@ -14,9 +14,8 @@
@RunWith(Parameterized.class)
public class VirtualMethodMergingOfPublicizedMethodsTest extends HorizontalClassMergingTestBase {
- public VirtualMethodMergingOfPublicizedMethodsTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public VirtualMethodMergingOfPublicizedMethodsTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -24,9 +23,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.allowAccessModification()
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/NotOverlappingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/NotOverlappingTest.java
index e405aa9..3d0fe4a 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/NotOverlappingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/NotOverlappingTest.java
@@ -13,8 +13,8 @@
import org.junit.Test;
public class NotOverlappingTest extends HorizontalClassMergingTestBase {
- public NotOverlappingTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public NotOverlappingTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -22,9 +22,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -32,14 +29,8 @@
.assertSuccessWithOutputLines("foo", "bar")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java
index 11164b1..3787201 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java
@@ -17,9 +17,8 @@
public class OverrideAbstractMethodWithDefaultTest extends HorizontalClassMergingTestBase {
- public OverrideAbstractMethodWithDefaultTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public OverrideAbstractMethodWithDefaultTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -27,15 +26,12 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, HorizontallyMergedClassesInspector::assertNoClassesMerged)
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("J", "B2")
.inspect(
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java
index 15ca564..d74ae0a 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java
@@ -16,9 +16,8 @@
import org.junit.Test;
public class OverrideDefaultMethodTest extends HorizontalClassMergingTestBase {
- public OverrideDefaultMethodTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public OverrideDefaultMethodTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,15 +25,12 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, HorizontallyMergedClassesInspector::assertNoClassesMerged)
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("I", "B", "J")
.inspect(
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java
index 2aea3d0..95dc561 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java
@@ -17,9 +17,8 @@
import org.junit.Test;
public class OverrideDefaultOnSuperMethodTest extends HorizontalClassMergingTestBase {
- public OverrideDefaultOnSuperMethodTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public OverrideDefaultOnSuperMethodTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -27,16 +26,13 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoUnusedInterfaceRemovalAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, HorizontallyMergedClassesInspector::assertNoClassesMerged)
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("I", "B", "J")
.inspect(
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideMergeAbsentTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideMergeAbsentTest.java
index 9a727f5..6f5e761 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideMergeAbsentTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideMergeAbsentTest.java
@@ -16,8 +16,8 @@
import org.junit.Test;
public class OverrideMergeAbsentTest extends HorizontalClassMergingTestBase {
- public OverrideMergeAbsentTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public OverrideMergeAbsentTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,15 +25,12 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .addHorizontallyMergedClassesInspectorIf(
- enableHorizontalClassMerging, HorizontallyMergedClassesInspector::assertNoClassesMerged)
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("A", "B", "A", "J")
.inspect(
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideParentCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideParentCollisionTest.java
index 639cf19..c62f59b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideParentCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideParentCollisionTest.java
@@ -16,9 +16,8 @@
public class OverrideParentCollisionTest extends HorizontalClassMergingTestBase {
- public OverrideParentCollisionTest(
- TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public OverrideParentCollisionTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -26,9 +25,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(this.getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -36,14 +32,8 @@
.assertSuccessWithOutputLines("foo", "bar", "foo", "parent")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
assertThat(codeInspector.clazz(B.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/SuperMethodMergedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/SuperMethodMergedTest.java
index 44973bc..fb2189d 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/SuperMethodMergedTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/SuperMethodMergedTest.java
@@ -16,8 +16,8 @@
import org.junit.Test;
public class SuperMethodMergedTest extends HorizontalClassMergingTestBase {
- public SuperMethodMergedTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- super(parameters, enableHorizontalClassMerging);
+ public SuperMethodMergedTest(TestParameters parameters) {
+ super(parameters);
}
@Test
@@ -25,9 +25,6 @@
testForR8(parameters.getBackend())
.addInnerClasses(this.getClass())
.addKeepMainRule(Main.class)
- .addOptionsModification(
- options ->
- options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
@@ -36,18 +33,10 @@
.assertSuccessWithOutputLines("foo", "parent b", "parent b", "x", "parent b")
.inspect(
codeInspector -> {
- if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(ParentA.class), isPresent());
assertThat(codeInspector.clazz(ParentB.class), not(isPresent()));
assertThat(codeInspector.clazz(X.class), isPresent());
assertThat(codeInspector.clazz(Y.class), not(isPresent()));
- // TODO(b/165517236): Explicitly check classes have been merged.
- } else {
- assertThat(codeInspector.clazz(ParentA.class), isPresent());
- assertThat(codeInspector.clazz(ParentB.class), isPresent());
- assertThat(codeInspector.clazz(X.class), isPresent());
- assertThat(codeInspector.clazz(Y.class), isPresent());
- }
});
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/B141942381.java b/src/test/java/com/android/tools/r8/classmerging/vertical/B141942381.java
index 97f84ef..d840b52 100644
--- a/src/test/java/com/android/tools/r8/classmerging/vertical/B141942381.java
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/B141942381.java
@@ -77,8 +77,8 @@
assertThat(set, isPresent());
assertEquals(
- set.getMethod().method.proto.parameters.values[0],
- storage.getField().field.type.toBaseType(inspector.getFactory()));
+ set.getMethod().getReference().proto.parameters.values[0],
+ storage.getField().getReference().type.toBaseType(inspector.getFactory()));
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java b/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java
index beed8fc..a292274 100644
--- a/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java
@@ -105,7 +105,7 @@
}
public static boolean fromAndroidN(Version dexVmVersion) {
- return dexVmVersion.isAtLeast(Version.V7_0_0);
+ return dexVmVersion.isNewerThanOrEqual(Version.V7_0_0);
}
private static List<Path> findAllJarsIn(Path root) {
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index a083bcf..c34c633 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -1050,8 +1050,8 @@
artCommandBuilder.appendArtOption("-Xcompiler-option");
artCommandBuilder.appendArtOption("--debuggable");
}
- if (ToolHelper.getDexVm().getVersion().isAtLeast(DexVm.Version.V9_0_0) &&
- ToolHelper.getDexVm().getVersion() != DexVm.Version.DEFAULT) {
+ if (ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(DexVm.Version.V9_0_0)
+ && ToolHelper.getDexVm().getVersion() != DexVm.Version.DEFAULT) {
artCommandBuilder.appendArtOption("-XjdwpProvider:internal");
}
if (DEBUG_TESTS && ToolHelper.getDexVm().getVersion().isNewerThan(Version.V4_4_4)) {
diff --git a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
index 67e62e8..12c6bc8 100644
--- a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
@@ -338,7 +338,7 @@
// See verifyStateLocation in DebugTestBase.
Assume.assumeTrue(
"Streaming on Dalvik DEX runtimes has some unknown interference issue",
- ToolHelper.getDexVm().getVersion().isAtLeast(Version.V6_0_1));
+ ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(Version.V6_0_1));
Assume.assumeTrue(
"Skipping test "
+ testName.getMethodName()
diff --git a/src/test/java/com/android/tools/r8/debug/IincDebugTestRunner.java b/src/test/java/com/android/tools/r8/debug/IincDebugTestRunner.java
index cfd0a98..3e7367e 100644
--- a/src/test/java/com/android/tools/r8/debug/IincDebugTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/IincDebugTestRunner.java
@@ -72,7 +72,7 @@
// See verifyStateLocation in DebugTestBase.
Assume.assumeTrue(
"Streaming on Dalvik DEX runtimes has some unknown interference issue",
- ToolHelper.getDexVm().getVersion().isAtLeast(Version.V6_0_1));
+ ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(Version.V6_0_1));
Assume.assumeTrue(
"Skipping test "
+ testName.getMethodName()
diff --git a/src/test/java/com/android/tools/r8/desugar/DefaultLambdaMethodWithPrivateSuperClassTest.java b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaMethodWithPrivateSuperClassTest.java
new file mode 100644
index 0000000..6ba2e12
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaMethodWithPrivateSuperClassTest.java
@@ -0,0 +1,81 @@
+// 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.desugar;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Regression test code for ensuring that desugared code behaves at least kind of like
+ * https://bugs.openjdk.java.net/browse/JDK-8021581
+ */
+@RunWith(Parameterized.class)
+public class DefaultLambdaMethodWithPrivateSuperClassTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DefaultLambdaMethodWithPrivateSuperClassTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ }
+
+ @Test
+ public void testDesugar() throws Exception {
+ testForD8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ parameters.isCfRuntime()
+ || parameters.getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.M),
+ r -> r.assertFailureWithErrorThatThrows(IllegalAccessError.class),
+ // TODO(b/152199517): Should be illegal access for DEX.
+ r -> r.assertSuccessWithOutputLines("interface"));
+ }
+
+ interface Named {
+
+ default String name() {
+ return "interface";
+ }
+
+ class PrivateNameBase {
+ private String name() {
+ throw new AssertionError("shouldn't get here");
+ }
+ }
+
+ class PrivateName extends PrivateNameBase implements Named {}
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ String unexpected = new Named.PrivateName().name();
+ System.out.println(unexpected);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/DefaultLambdaMethodWithPublicSuperClassTest.java b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaMethodWithPublicSuperClassTest.java
new file mode 100644
index 0000000..a439984
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaMethodWithPublicSuperClassTest.java
@@ -0,0 +1,71 @@
+// 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.desugar;
+
+import static org.junit.Assume.assumeTrue;
+
+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.Parameters;
+
+@RunWith(Parameterized.class)
+public class DefaultLambdaMethodWithPublicSuperClassTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final String EXPECTED = "PublicNameBase::name";
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DefaultLambdaMethodWithPublicSuperClassTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testDesugar() throws Exception {
+ testForD8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ interface Named {
+
+ default String name() {
+ return "interface";
+ }
+
+ class PublicNameBase {
+ public String name() {
+ return "PublicNameBase::name";
+ }
+ }
+
+ class PublicName extends PublicNameBase implements Named {}
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ System.out.println(new Named.PublicName().name());
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java
index 477af87..409d776 100644
--- a/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java
+++ b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java
@@ -178,8 +178,8 @@
DisassembleCommand.builder().addProgramFiles(out1).setOutputPath(dissasemble1).build());
Disassemble.disassemble(
DisassembleCommand.builder().addProgramFiles(out2).setOutputPath(dissasemble2).build());
- String content1 = StringUtils.join(Files.readAllLines(dissasemble1), "\n");
- String content2 = StringUtils.join(Files.readAllLines(dissasemble2), "\n");
+ String content1 = StringUtils.join("\n", Files.readAllLines(dissasemble1));
+ String content2 = StringUtils.join("\n", Files.readAllLines(dissasemble2));
assertEquals(content1, content2);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index 784e875..646dbf9 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -102,10 +102,7 @@
.apply(this::configureProgram)
.setIncludeClassesChecksum(true)
.compile()
- .run(
- parameters.getRuntime(),
- testClassName,
- parameters.getRuntime().asDex().getVm().getVersion().toString())
+ .run(parameters.getRuntime(), testClassName)
.assertSuccess()
.inspect(this::assertDesugaring);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java
new file mode 100644
index 0000000..57d8867
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java
@@ -0,0 +1,162 @@
+// 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.
+
+package com.android.tools.r8.desugar.desugaredlibrary;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assume;
+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 CustomMapHierarchyTest extends DesugaredLibraryTestBase {
+
+ private static final String EXPECTED =
+ StringUtils.lines("B::getOrDefault", "default 1", "B::getOrDefault", "default 2");
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+
+ @Parameters(name = "{0}, shrinkDesugaredLibrary: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
+ BooleanUtils.values());
+ }
+
+ public CustomMapHierarchyTest(TestParameters parameters, boolean shrinkDesugaredLibrary) {
+ this.parameters = parameters;
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ }
+
+ @Test
+ public void testWithoutLibraryDesugaring() throws Exception {
+ Assume.assumeTrue(
+ parameters.getRuntime().isCf()
+ || parameters
+ .getApiLevel()
+ .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport()));
+ testForRuntime(parameters)
+ .addInnerClasses(CustomMapHierarchyTest.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ Assume.assumeTrue(parameters.getRuntime().isDex());
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ testForD8()
+ .addInnerClasses(CustomMapHierarchyTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testD8Cf2Cf() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+
+ Path jar =
+ testForD8(Backend.CF)
+ .addInnerClasses(CustomMapHierarchyTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .setIncludeClassesChecksum(true)
+ .setMinApi(parameters.getApiLevel())
+ .allowStdoutMessages()
+ .compile()
+ .writeToZip();
+ String desugaredLibraryKeepRules = "";
+ if (shrinkDesugaredLibrary && keepRuleConsumer.get() != null) {
+ // Collection keep rules is only implemented in the DEX writer.
+ assertEquals(0, keepRuleConsumer.get().length());
+ desugaredLibraryKeepRules = "-keep class * { *; }";
+ }
+ if (parameters.getRuntime().isDex()) {
+ testForD8()
+ .addProgramFiles(jar)
+ .setMinApi(parameters.getApiLevel())
+ .disableDesugaring()
+ .allowStdoutMessages()
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ desugaredLibraryKeepRules,
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ testForJvm()
+ .addProgramFiles(jar)
+ .addRunClasspathFiles(getDesugaredLibraryInCF(parameters, options -> {}))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ Assume.assumeTrue(parameters.getRuntime().isDex());
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ testForR8(parameters.getBackend())
+ .addInnerClasses(CustomMapHierarchyTest.class)
+ .addKeepMainRule(Main.class)
+ .addKeepAllClassesRuleWithAllowObfuscation()
+ .addKeepAttributes(
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ public static class Main {
+ public static void main(String[] args) {
+ System.out.println(new B<String>().getOrDefault("Not found", "default 1"));
+ System.out.println(
+ ((Map<String, String>) new B<String>()).getOrDefault("Not found", "default 2"));
+ }
+ }
+
+ abstract static class A<T> extends LinkedHashMap<T, T> {}
+
+ // AbstractSequentialList implements List further up the hierarchy.
+ static class B<T> extends A<T> {
+ // Need at least one overridden default method for emulated dispatch.
+ @Override
+ public T getOrDefault(Object key, T defaultValue) {
+ System.out.println("B::getOrDefault");
+ return super.getOrDefault(key, defaultValue);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
index a3b768d..af6ca9e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
@@ -9,15 +9,23 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.nio.file.Path;
import java.time.LocalDate;
+import java.util.AbstractSequentialList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.function.UnaryOperator;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,7 +37,6 @@
private final TestParameters parameters;
private final boolean shrinkDesugaredLibrary;
- private static final String EXPECTED = StringUtils.lines("1970", "1", "2");
@Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
public static List<Object[]> data() {
@@ -60,7 +67,7 @@
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutput(EXPECTED);
+ .assertSuccessWithOutput(expected(parameters, false));
}
@Test
@@ -96,13 +103,13 @@
desugaredLibraryKeepRules,
shrinkDesugaredLibrary)
.run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutput(EXPECTED);
+ .assertSuccessWithOutput(expected(parameters, true));
} else {
testForJvm()
.addProgramFiles(jar)
.addRunClasspathFiles(getDesugaredLibraryInCF(parameters, options -> {}))
.run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutput(EXPECTED);
+ .assertSuccessWithOutput(expected(parameters, true));
}
}
@@ -129,7 +136,7 @@
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutput(EXPECTED);
+ .assertSuccessWithOutput(expected(parameters, false));
}
private void checkRewrittenSignature(CodeInspector inspector) {
@@ -149,6 +156,7 @@
}
public interface Box<T> {
+
T addOne(T t);
}
@@ -161,6 +169,61 @@
}
}
+ private static String expected(
+ TestParameters parameters, boolean genericSignaturesOnEmulatedInterfaces) {
+ final String EXPECTED = StringUtils.lines("Box", "1970", "1", "2");
+ final String STRING_KEY_HASH_MAP_EXPECTED =
+ StringUtils.lines(
+ "StringKeyHashMap", "1", "j$.util.Map<java.lang.String, T>", "2", "true", "true");
+ final String SAME_KEY_AND_VALUE_TYPE_HASH_MAP_EXPECTED =
+ StringUtils.lines(
+ "SameKeyAndValueTypeHashMap", "1", "j$.util.Map<T, T>", "2", "true", "true");
+ final String TRANSFORMING_SEQUENTIAL_LIST_EXPECTED =
+ StringUtils.lines("TransformingSequentialList", "2", "j$.util.List<T>");
+
+ final String EXPECTED_WITH_EMULATED_INTERFACE =
+ STRING_KEY_HASH_MAP_EXPECTED
+ + SAME_KEY_AND_VALUE_TYPE_HASH_MAP_EXPECTED
+ + TRANSFORMING_SEQUENTIAL_LIST_EXPECTED;
+ final String EXPECTED_WITHOUT_EMULATED_INTERFACE_ART_BEFORE_O =
+ StringUtils.lines(
+ "StringKeyHashMap",
+ "1",
+ "interface j$.util.Map",
+ "SameKeyAndValueTypeHashMap",
+ "1",
+ "interface j$.util.Map",
+ "TransformingSequentialList",
+ "2",
+ "interface j$.util.List");
+ final String EXPECTED_WITHOUT_EMULATED_INTERFACE_JVM_AND_ART_FROM_O =
+ StringUtils.lines(
+ "StringKeyHashMap",
+ "0",
+ "SameKeyAndValueTypeHashMap",
+ "0",
+ "TransformingSequentialList",
+ "1");
+
+ return EXPECTED
+ + (genericSignaturesOnEmulatedInterfaces
+ && !parameters
+ .getApiLevel()
+ .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport())
+ ? EXPECTED_WITH_EMULATED_INTERFACE
+ : (parameters.isDexRuntime()
+ && (parameters
+ .getRuntime()
+ .asDex()
+ .getMinApiLevel()
+ .isLessThan(AndroidApiLevel.N)
+ || parameters
+ .getApiLevel()
+ .isLessThan(TestBase.apiLevelWithDefaultInterfaceMethodsSupport())))
+ ? EXPECTED_WITHOUT_EMULATED_INTERFACE_ART_BEFORE_O
+ : EXPECTED_WITHOUT_EMULATED_INTERFACE_JVM_AND_ART_FROM_O);
+ }
+
public static class Main {
public static Box<java.time.LocalDate> bar() {
@@ -168,10 +231,96 @@
}
public static void main(String[] args) {
+ testBox();
+ testEmulatedInterfaceGenericSignatureStringKeyHashMap();
+ testEmulatedInterfaceGenericSignatureSameKeyAndValueTypeHashMap();
+ testEmulatedInterfaceGenericSignatureTransformingSequentialList();
+ }
+
+ public static void testBox() {
+ System.out.println("Box");
LocalDate localDate = bar().addOne(LocalDate.of(1970, 1, 1));
System.out.println(localDate.getYear());
System.out.println(localDate.getMonthValue());
System.out.println(localDate.getDayOfMonth());
}
+
+ public static void testEmulatedInterfaceGenericSignatureStringKeyHashMap() {
+ System.out.println("StringKeyHashMap");
+ Class<?> clazz = StringKeyHashMap.class;
+ System.out.println(clazz.getGenericInterfaces().length);
+ if (clazz.getGenericInterfaces().length == 0) {
+ return;
+ }
+ Type genericInterface = clazz.getGenericInterfaces()[0];
+ System.out.println(genericInterface);
+ if (genericInterface instanceof ParameterizedType) {
+ // The j$.util.Map emulated interface has the generic type arguments <String, T>.
+ Type[] actualTypeArguments =
+ ((ParameterizedType) genericInterface).getActualTypeArguments();
+ System.out.println(actualTypeArguments.length);
+ System.out.println(actualTypeArguments[0].equals(String.class));
+ System.out.println(actualTypeArguments[1].equals(clazz.getTypeParameters()[0]));
+ }
+ }
+
+ public static void testEmulatedInterfaceGenericSignatureSameKeyAndValueTypeHashMap() {
+ System.out.println("SameKeyAndValueTypeHashMap");
+ Class<?> clazz = SameKeyAndValueTypeHashMap.class;
+ System.out.println(clazz.getGenericInterfaces().length);
+ if (clazz.getGenericInterfaces().length == 0) {
+ return;
+ }
+ Type genericInterface = clazz.getGenericInterfaces()[0];
+ System.out.println(genericInterface);
+ if (genericInterface instanceof ParameterizedType) {
+ // The j$.util.Map emulated interface has the generic type arguments <T, T>.
+ Type[] actualTypeArguments =
+ ((ParameterizedType) genericInterface).getActualTypeArguments();
+ System.out.println(actualTypeArguments.length);
+ System.out.println(actualTypeArguments[0].equals(clazz.getTypeParameters()[0]));
+ System.out.println(actualTypeArguments[1].equals(clazz.getTypeParameters()[0]));
+ }
+ }
+
+ public static void testEmulatedInterfaceGenericSignatureTransformingSequentialList() {
+ System.out.println("TransformingSequentialList");
+ Class<?> clazz = TransformingSequentialList.class;
+ System.out.println(clazz.getGenericInterfaces().length);
+ if (clazz.getGenericInterfaces().length == 1) {
+ return;
+ }
+ // j$.util.List emulated interface has the generic type argument <T>.
+ System.out.println(clazz.getGenericInterfaces()[1]);
+ }
+ }
+
+ // LinkedHashMap implements Map.
+ abstract static class StringKeyHashMap<T> extends LinkedHashMap<String, T> {
+
+ // Need at least one overridden default method for emulated dispatch.
+ @Override
+ public T getOrDefault(Object key, T defaultValue) {
+ return super.getOrDefault(key, defaultValue);
+ }
+ }
+
+ // LinkedHashMap implements Map.
+ abstract static class SameKeyAndValueTypeHashMap<T> extends LinkedHashMap<T, T> {
+
+ // Need at least one overridden default method for emulated dispatch.
+ @Override
+ public T getOrDefault(Object key, T defaultValue) {
+ return super.getOrDefault(key, defaultValue);
+ }
+ }
+
+ // AbstractSequentialList implements List further up the hierarchy.
+ abstract static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
+ implements Serializable {
+
+ // Need at least one overridden default method for emulated dispatch.
+ @Override
+ public void replaceAll(UnaryOperator<T> operator) {}
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DumpCoreLibUsage.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DumpCoreLibUsage.java
index 62d2d3a..ae4eda0 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DumpCoreLibUsage.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DumpCoreLibUsage.java
@@ -85,13 +85,13 @@
if (!field.accessFlags.isPublic()) {
continue;
}
- if (filter.contains(field.field)) {
+ if (filter.contains(field.getReference())) {
continue;
}
- if (usesTypeFromPackage(pkg, field.field)) {
+ if (usesTypeFromPackage(pkg, field.getReference())) {
headerWritten = writeHeaderIfNeeded(libraryClass.type, headerWritten);
System.out.println(" " + field.toSourceString());
- found.add(field.field);
+ found.add(field.getReference());
}
}
@@ -105,13 +105,13 @@
if (method.isSyntheticMethod()) {
continue;
}
- if (filter.contains(method.method)) {
+ if (filter.contains(method.getReference())) {
continue;
}
- if (usesTypeFromPackage(pkg, method.method)) {
+ if (usesTypeFromPackage(pkg, method.getReference())) {
headerWritten = writeHeaderIfNeeded(libraryClass.type, headerWritten);
- System.out.println(" " + method.method.toSourceStringWithoutHolder());
- found.add(method.method);
+ System.out.println(" " + method.getReference().toSourceStringWithoutHolder());
+ found.add(method.getReference());
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
index e345069..32d9d95 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
@@ -16,7 +16,6 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.List;
import java.util.function.Function;
-import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -51,7 +50,7 @@
classSubject
.uniqueMethodWithName("applyFunction")
.getMethod()
- .method
+ .getReference()
.proto
.parameters
.values[0]
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LintFilesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LintFilesTest.java
index 43f53ab..624e8a0 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LintFilesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LintFilesTest.java
@@ -11,6 +11,8 @@
import com.android.tools.r8.GenerateLintFiles;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
@@ -26,9 +28,22 @@
import java.util.List;
import org.junit.Assume;
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 LintFilesTest extends TestBase {
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public LintFilesTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
private void checkFileContent(AndroidApiLevel minApiLevel, Path lintFile) throws Exception {
// Just do some light probing in the generated lint files.
List<String> methods = FileUtils.readAllLines(lintFile);
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
index cb8c24f..e23e86d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
@@ -64,7 +64,7 @@
.anyMatch(
m ->
m.getMethod()
- .method
+ .getReference()
.proto
.parameters
.values[0]
@@ -75,7 +75,7 @@
.anyMatch(
m ->
m.getMethod()
- .method
+ .getReference()
.proto
.parameters
.values[0]
@@ -210,9 +210,9 @@
virtualMethods.stream()
.anyMatch(
m ->
- m.getMethod().method.name.toString().equals("foo")
+ m.getMethod().getReference().name.toString().equals("foo")
&& m.getMethod()
- .method
+ .getReference()
.proto
.parameters
.values[0]
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
index 0ee446d..5cd8c8d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
@@ -121,7 +121,7 @@
IterableUtils.size(
myCollection
.getDexProgramClass()
- .virtualMethods(m -> m.method.name.toString().equals("forEach"))));
+ .virtualMethods(m -> m.getReference().name.toString().equals("forEach"))));
}
private void assertWrapperMethodsPresent(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java
index b38e710..47320d8 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java
@@ -86,16 +86,19 @@
private boolean isNestBridge(FoundMethodSubject methodSubject) {
DexEncodedMethod method = methodSubject.getMethod();
if (method.isInstanceInitializer()) {
- if (method.method.proto.parameters.isEmpty()) {
+ if (method.getReference().proto.parameters.isEmpty()) {
return false;
}
- DexType[] formals = method.method.proto.parameters.values;
+ DexType[] formals = method.getReference().proto.parameters.values;
DexType lastFormal = formals[formals.length - 1];
return lastFormal.isClassType()
&& SyntheticItemsTestUtils.isInitializerTypeArgument(
Reference.classFromDescriptor(lastFormal.toDescriptorString()));
}
- return method.method.name.toString()
+ return method
+ .getReference()
+ .name
+ .toString()
.startsWith(NestBasedAccessDesugaring.NEST_ACCESS_NAME_PREFIX);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/records/EmptyRecordTest.java b/src/test/java/com/android/tools/r8/desugar/records/EmptyRecordTest.java
index 2e97d1e..9f9dd85 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/EmptyRecordTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/EmptyRecordTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
import java.util.List;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -35,20 +36,35 @@
public static List<Object[]> data() {
// TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
return buildParameters(
- getTestParameters().withCustomRuntime(CfRuntime.getCheckedInJdk15()).build());
+ getTestParameters()
+ .withCustomRuntime(CfRuntime.getCheckedInJdk15())
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build());
}
@Test
- public void testJvm() throws Exception {
- testForJvm()
+ public void testD8AndJvm() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClassFileData(PROGRAM_DATA)
+ .enablePreview()
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+ testForD8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
- .enablePreview()
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
.run(parameters.getRuntime(), MAIN_TYPE)
.assertSuccessWithOutput(EXPECTED_RESULT);
}
@Test
public void testR8Cf() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
Path output =
testForR8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
diff --git a/src/test/java/com/android/tools/r8/desugar/records/GenerateRecordMethods.java b/src/test/java/com/android/tools/r8/desugar/records/GenerateRecordMethods.java
new file mode 100644
index 0000000..53d6201
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/records/GenerateRecordMethods.java
@@ -0,0 +1,118 @@
+// 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.desugar.records;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfTypeInstruction;
+import com.android.tools.r8.cfmethodgeneration.MethodGenerationBase;
+import com.android.tools.r8.graph.CfCode;
+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.ir.desugar.RecordRewriter;
+import com.android.tools.r8.utils.FileUtils;
+import com.google.common.collect.ImmutableList;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+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 GenerateRecordMethods extends MethodGenerationBase {
+ private final DexType GENERATED_TYPE =
+ factory.createType("Lcom/android/tools/r8/ir/desugar/RecordCfMethods;");
+ private final List<Class<?>> METHOD_TEMPLATE_CLASSES = ImmutableList.of(RecordMethods.class);
+
+ protected final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withCfRuntime(CfVm.JDK9).build();
+ }
+
+ public GenerateRecordMethods(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Override
+ protected DexType getGeneratedType() {
+ return GENERATED_TYPE;
+ }
+
+ @Override
+ protected List<Class<?>> getMethodTemplateClasses() {
+ return METHOD_TEMPLATE_CLASSES;
+ }
+
+ @Override
+ protected int getYear() {
+ return 2021;
+ }
+
+ @Override
+ protected CfCode getCode(String holderName, String methodName, CfCode code) {
+ DexType recordStubType =
+ factory.createType("Lcom/android/tools/r8/desugar/records/RecordMethods$RecordStub;");
+ code.setInstructions(
+ code.getInstructions().stream()
+ .map(instruction -> rewriteRecordStub(factory, instruction, recordStubType))
+ .collect(Collectors.toList()));
+ return code;
+ }
+
+ private CfInstruction rewriteRecordStub(
+ DexItemFactory factory, CfInstruction instruction, DexType recordStubType) {
+ if (instruction.isTypeInstruction()) {
+ CfTypeInstruction typeInstruction = instruction.asTypeInstruction();
+ return typeInstruction.withType(
+ rewriteType(factory, recordStubType, typeInstruction.getType()));
+ }
+ if (instruction.isInvoke()) {
+ CfInvoke cfInvoke = instruction.asInvoke();
+ DexMethod method = cfInvoke.getMethod();
+ DexMethod newMethod =
+ factory.createMethod(
+ rewriteType(factory, recordStubType, method.holder),
+ method.proto,
+ rewriteName(method.name));
+ return new CfInvoke(cfInvoke.getOpcode(), newMethod, cfInvoke.isInterface());
+ }
+ return instruction;
+ }
+
+ private String rewriteName(DexString name) {
+ return name.toString().equals("getFieldsAsObjects")
+ ? RecordRewriter.GET_FIELDS_AS_OBJECTS_METHOD_NAME
+ : name.toString();
+ }
+
+ private DexType rewriteType(DexItemFactory factory, DexType recordStubType, DexType type) {
+ return type == recordStubType ? factory.recordType : type;
+ }
+
+ @Test
+ public void testRecordMethodsGenerated() throws Exception {
+ ArrayList<Class<?>> sorted = new ArrayList<>(getMethodTemplateClasses());
+ sorted.sort(Comparator.comparing(Class::getTypeName));
+ assertEquals("Classes should be listed in sorted order", sorted, getMethodTemplateClasses());
+ assertEquals(
+ FileUtils.readTextFile(getGeneratedFile(), StandardCharsets.UTF_8), generateMethods());
+ }
+
+ public static void main(String[] args) throws Exception {
+ new GenerateRecordMethods(null).generateMethodsAndWriteThemToFile();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordInstanceOfTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordInstanceOfTest.java
index 5fce5e2..d388ac4 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/RecordInstanceOfTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordInstanceOfTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
import java.util.List;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -35,20 +36,35 @@
public static List<Object[]> data() {
// TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
return buildParameters(
- getTestParameters().withCustomRuntime(CfRuntime.getCheckedInJdk15()).build());
+ getTestParameters()
+ .withCustomRuntime(CfRuntime.getCheckedInJdk15())
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build());
}
@Test
- public void testJvm() throws Exception {
- testForJvm()
+ public void testD8AndJvm() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClassFileData(PROGRAM_DATA)
+ .enablePreview()
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+ testForD8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
- .enablePreview()
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
.run(parameters.getRuntime(), MAIN_TYPE)
.assertSuccessWithOutput(EXPECTED_RESULT);
}
@Test
public void testR8Cf() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
Path output =
testForR8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordInvokeCustomTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordInvokeCustomTest.java
index 071af85..711909f 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/RecordInvokeCustomTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordInvokeCustomTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
import java.util.List;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -48,20 +49,35 @@
public static List<Object[]> data() {
// TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
return buildParameters(
- getTestParameters().withCustomRuntime(CfRuntime.getCheckedInJdk15()).build());
+ getTestParameters()
+ .withCustomRuntime(CfRuntime.getCheckedInJdk15())
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build());
}
@Test
- public void testJvm() throws Exception {
- testForJvm()
+ public void testD8AndJvm() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClassFileData(PROGRAM_DATA)
+ .enablePreview()
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+ testForD8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
- .enablePreview()
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
.run(parameters.getRuntime(), MAIN_TYPE)
.assertSuccessWithOutput(EXPECTED_RESULT);
}
@Test
public void testR8Cf() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
Path output =
testForR8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordMergeTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordMergeTest.java
new file mode 100644
index 0000000..bd08a25
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordMergeTest.java
@@ -0,0 +1,101 @@
+// 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.desugar.records;
+
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.utils.InternalOptions.TestingOptions;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RecordMergeTest extends TestBase {
+
+ private static final String RECORD_NAME_1 = "RecordWithMembers";
+ private static final byte[][] PROGRAM_DATA_1 = RecordTestUtils.getProgramData(RECORD_NAME_1);
+ private static final String MAIN_TYPE_1 = RecordTestUtils.getMainType(RECORD_NAME_1);
+ private static final String EXPECTED_RESULT_1 =
+ StringUtils.lines(
+ "BobX", "43", "BobX", "43", "FelixX", "-1", "FelixX", "-1", "print", "Bob43", "extra");
+
+ private static final String RECORD_NAME_2 = "SimpleRecord";
+ private static final byte[][] PROGRAM_DATA_2 = RecordTestUtils.getProgramData(RECORD_NAME_2);
+ private static final String MAIN_TYPE_2 = RecordTestUtils.getMainType(RECORD_NAME_2);
+ private static final String EXPECTED_RESULT_2 =
+ StringUtils.lines("Jane Doe", "42", "Jane Doe", "42");
+
+ private final TestParameters parameters;
+
+ public RecordMergeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ // TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
+ return buildParameters(
+ getTestParameters()
+ .withCustomRuntime(CfRuntime.getCheckedInJdk15())
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build());
+ }
+
+ @Test
+ public void testMergeDesugaredInputs() throws Exception {
+ Path output1 =
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(PROGRAM_DATA_1)
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
+ .writeToZip();
+ Path output2 =
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(PROGRAM_DATA_2)
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
+ .writeToZip();
+ D8TestCompileResult result =
+ testForD8(parameters.getBackend())
+ .addProgramFiles(output1, output2)
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .compile();
+ result.run(parameters.getRuntime(), MAIN_TYPE_1).assertSuccessWithOutput(EXPECTED_RESULT_1);
+ result.run(parameters.getRuntime(), MAIN_TYPE_2).assertSuccessWithOutput(EXPECTED_RESULT_2);
+ }
+
+ @Test
+ public void testMergeDesugaredAndNonDesugaredInputs() throws Exception {
+ Path output1 =
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(PROGRAM_DATA_1)
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
+ .writeToZip();
+ D8TestCompileResult result =
+ testForD8(parameters.getBackend())
+ .addProgramFiles(output1)
+ .addProgramClassFileData(PROGRAM_DATA_2)
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile();
+ result.run(parameters.getRuntime(), MAIN_TYPE_1).assertSuccessWithOutput(EXPECTED_RESULT_1);
+ result.run(parameters.getRuntime(), MAIN_TYPE_2).assertSuccessWithOutput(EXPECTED_RESULT_2);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordMethods.java b/src/test/java/com/android/tools/r8/desugar/records/RecordMethods.java
new file mode 100644
index 0000000..7b1b2e5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordMethods.java
@@ -0,0 +1,43 @@
+// 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.desugar.records;
+
+import java.util.Arrays;
+
+// This class implements support methods for record desugaring. The RecordRewriter
+// rewrites relevant calls to one of the following methods.
+public class RecordMethods {
+
+ public static String toString(RecordStub recordInstance, String simpleName, String fieldNames) {
+ // Example: "Person[name=Jane Doe, age=42]"
+ String[] fieldNamesSplit = fieldNames.isEmpty() ? new String[0] : fieldNames.split(";");
+ Object[] fields = recordInstance.getFieldsAsObjects();
+ StringBuilder builder = new StringBuilder();
+ builder.append(simpleName).append("[");
+ for (int i = 0; i < fieldNamesSplit.length; i++) {
+ builder.append(fieldNamesSplit[i]).append("=").append(fields[i]);
+ if (i != fieldNamesSplit.length - 1) {
+ builder.append(", ");
+ }
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static int hashCode(RecordStub recordInstance) {
+ return 31 * Arrays.hashCode(recordInstance.getFieldsAsObjects())
+ + recordInstance.getClass().hashCode();
+ }
+
+ public static boolean equals(RecordStub recordInstance, Object other) {
+ return recordInstance.getClass() == other.getClass()
+ && Arrays.equals(
+ ((RecordStub) other).getFieldsAsObjects(), recordInstance.getFieldsAsObjects());
+ }
+
+ public abstract static class RecordStub {
+ abstract Object[] getFieldsAsObjects();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordWithMembersTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordWithMembersTest.java
index 610b061..5472f22 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/RecordWithMembersTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordWithMembersTest.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.desugar.records.RecordTestUtils.RECORD_KEEP_RULE;
-import com.android.tools.r8.Jdk9TestUtils;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfRuntime;
@@ -14,6 +13,7 @@
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
import java.util.List;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -38,24 +38,38 @@
public static List<Object[]> data() {
// TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
return buildParameters(
- getTestParameters().withCustomRuntime(CfRuntime.getCheckedInJdk15()).build());
+ getTestParameters()
+ .withCustomRuntime(CfRuntime.getCheckedInJdk15())
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build());
}
@Test
- public void testJvm() throws Exception {
- testForJvm()
+ public void testD8AndJvm() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClassFileData(PROGRAM_DATA)
+ .enablePreview()
+ .run(parameters.getRuntime(), MAIN_TYPE)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+ testForD8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
- .enablePreview()
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+ .addOptionsModification(opt -> opt.testing.enableExperimentalRecordDesugaring = true)
+ .compile()
.run(parameters.getRuntime(), MAIN_TYPE)
.assertSuccessWithOutput(EXPECTED_RESULT);
}
@Test
public void testR8Cf() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
Path output =
testForR8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
- .addLibraryFiles(Jdk9TestUtils.getJdk9LibraryFiles(temp))
.setMinApi(parameters.getApiLevel())
.addKeepRules(RECORD_KEEP_RULE)
.addKeepMainRule(MAIN_TYPE)
diff --git a/src/test/java/com/android/tools/r8/desugar/records/SimpleRecordTest.java b/src/test/java/com/android/tools/r8/desugar/records/SimpleRecordTest.java
index d5d2b1a..4820c08 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/SimpleRecordTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/SimpleRecordTest.java
@@ -40,7 +40,7 @@
getTestParameters()
.withCustomRuntime(CfRuntime.getCheckedInJdk15())
.withDexRuntimes()
- .withAllApiLevels()
+ .withAllApiLevelsAlsoForCf()
.build());
}
@@ -52,10 +52,8 @@
.enablePreview()
.run(parameters.getRuntime(), MAIN_TYPE)
.assertSuccessWithOutput(EXPECTED_RESULT);
- // TODO(b/179146128): Add a test for D8 cf to cf.
- return;
}
- testForD8()
+ testForD8(parameters.getBackend())
.addProgramClassFileData(PROGRAM_DATA)
.setMinApi(parameters.getApiLevel())
.addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionInvokeVirtualTest.java
similarity index 96%
rename from src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
rename to src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionInvokeVirtualTest.java
index e2474ca..cd2b968 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionInvokeVirtualTest.java
@@ -22,7 +22,7 @@
import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
-public class DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest
+public class DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionInvokeVirtualTest
extends TestBase {
private static final String EXPECTED = StringUtils.lines("I.m()");
@@ -36,7 +36,7 @@
getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
}
- public DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest(
+ public DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionInvokeVirtualTest(
TestParameters parameters, boolean invalidInvoke) {
this.parameters = parameters;
this.invalidInvoke = invalidInvoke;
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest.java
similarity index 75%
rename from src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionTest.java
rename to src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest.java
index c649c8d..3a55d74 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest.java
@@ -1,3 +1,6 @@
+// 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.desugaring.interfacemethods;
import static org.junit.Assume.assumeTrue;
@@ -11,7 +14,7 @@
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
-public class DefaultInterfaceMethodDesugaringWithStaticResolutionTest extends TestBase {
+public class DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest extends TestBase {
private static final String EXPECTED = StringUtils.lines("I.m()");
@@ -22,7 +25,8 @@
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public DefaultInterfaceMethodDesugaringWithStaticResolutionTest(TestParameters parameters) {
+ public DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest(
+ TestParameters parameters) {
this.parameters = parameters;
}
@@ -39,7 +43,7 @@
public void testD8() throws Exception {
assumeTrue(parameters.isDexRuntime());
testForD8()
- .addInnerClasses(DefaultInterfaceMethodDesugaringWithStaticResolutionTest.class)
+ .addInnerClasses(DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest.class)
.setMinApi(parameters.getApiLevel())
.compile()
.run(parameters.getRuntime(), TestClass.class)
@@ -49,7 +53,7 @@
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addInnerClasses(DefaultInterfaceMethodDesugaringWithStaticResolutionTest.class)
+ .addInnerClasses(DefaultInterfaceMethodDesugaringWithPrivateStaticResolutionTest.class)
.addKeepAllClassesRule()
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionInvokeVirtualTest.java
similarity index 64%
copy from src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
copy to src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionInvokeVirtualTest.java
index e2474ca..b968127 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionInvokeVirtualTest.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRunResult;
-import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -22,10 +21,11 @@
import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
-public class DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest
+public class DefaultInterfaceMethodDesugaringWithPublicStaticResolutionInvokeVirtualTest
extends TestBase {
private static final String EXPECTED = StringUtils.lines("I.m()");
+ private static final String EXPECTED_R8 = StringUtils.lines("B.m()");
private final TestParameters parameters;
private final boolean invalidInvoke;
@@ -33,10 +33,11 @@
@Parameterized.Parameters(name = "{0}, invalid:{1}")
public static List<Object[]> data() {
return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
+ BooleanUtils.values());
}
- public DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest(
+ public DefaultInterfaceMethodDesugaringWithPublicStaticResolutionInvokeVirtualTest(
TestParameters parameters, boolean invalidInvoke) {
this.parameters = parameters;
this.invalidInvoke = invalidInvoke;
@@ -53,8 +54,6 @@
B.class.getDeclaredMethod("m"),
flags -> {
assert flags.isPublic();
- flags.unsetPublic();
- flags.setPrivate();
flags.setStatic();
})
.transform(),
@@ -83,7 +82,8 @@
testForRuntime(parameters)
.addProgramClasses(getProgramClasses())
.addProgramClassFileData(getProgramClassData())
- .run(parameters.getRuntime(), TestClass.class));
+ .run(parameters.getRuntime(), TestClass.class),
+ false);
}
@Test
@@ -95,56 +95,36 @@
.addKeepAllClassesRule()
.setMinApi(parameters.getApiLevel())
.compile()
- .run(parameters.getRuntime(), TestClass.class));
+ .run(parameters.getRuntime(), TestClass.class),
+ true);
}
- private void checkResult(TestRunResult<?> result) {
+ private void checkResult(TestRunResult<?> result, boolean isR8) {
// Invalid invoke case is where the invoke-virtual targets C.m.
if (invalidInvoke) {
- // Up to 4.4 the exception for targeting a private static was ICCE.
- if (isDexOlderThanOrEqual(Version.V4_4_4)) {
+ if (parameters.isCfRuntime()) {
result.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
return;
}
- // Then up to 6.0 the runtime just ignores privates leading to incorrectly hitting I.m
- if (isDexOlderThanOrEqual(Version.V6_0_1)) {
+ if (parameters.getDexRuntimeVersion().isInRangeInclusive(Version.V5_1_1, Version.V7_0_0)) {
result.assertSuccessWithOutput(EXPECTED);
return;
}
- if (!unexpectedArtFailure() && !parameters.canUseDefaultAndStaticInterfaceMethods()) {
- assert false : "Dead code until future ART behavior change. See b/152199517";
- // Desugaring will insert a forwarding bridge which will hide the "invalid invoke" case.
- // Thus, a future ART runtime that does not have the invalid IAE for the private override
- // will end up calling the forward method to I.m.
- result.assertSuccessWithOutput(EXPECTED);
- }
- // The expected behavior is IAE since the resolved method is private.
- result.assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ result.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
return;
}
- // The non-invalid case is where the invoke-virtual targets A.m.
-
- // In the successful case ART since 6.0 incorrectly throws IAE due to the private override.
- if (unexpectedArtFailure()) {
- result.assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ if (isR8
+ && parameters.isDexRuntime()
+ && parameters.getDexRuntimeVersion().isNewerThan(Version.V6_0_1)) {
+ // TODO(b/1822553980: This should be EXPECTED.
+ result.assertSuccessWithOutput(EXPECTED_R8);
return;
}
- // The expected behavior is that the resolution of A.m will resolve and hit I.m.
result.assertSuccessWithOutput(EXPECTED);
}
- private boolean isDexOlderThanOrEqual(Version version) {
- return parameters.isDexRuntime()
- && parameters.getRuntime().asDex().getVm().getVersion().isOlderThanOrEqual(version);
- }
-
- private boolean unexpectedArtFailure() {
- return parameters.isDexRuntime()
- && parameters.getRuntime().asDex().getVm().isNewerThan(DexVm.ART_6_0_1_HOST);
- }
-
static class TestClass {
public static void main(String[] args) {
@@ -165,7 +145,7 @@
static class B extends A {
- public /* will be: private static */ void m() {
+ public /* will be: public static */ void m() {
System.out.println("B.m()");
}
}
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionOnClassTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionOnClassTest.java
new file mode 100644
index 0000000..1684c5a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionOnClassTest.java
@@ -0,0 +1,115 @@
+// 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.desugaring.interfacemethods;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+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.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DefaultInterfaceMethodDesugaringWithPublicStaticResolutionOnClassTest
+ extends TestBase {
+
+ private static final String EXPECTED_INVALID = StringUtils.lines("I.m()");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DefaultInterfaceMethodDesugaringWithPublicStaticResolutionOnClassTest(
+ TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ private Collection<Class<?>> getProgramClasses() {
+ return ImmutableList.of(TestClass.class, I.class, B.class);
+ }
+
+ private Collection<byte[]> getProgramClassData() throws Exception {
+ return ImmutableList.of(
+ transformer(A.class)
+ .setAccessFlags(
+ A.class.getDeclaredMethod("m"),
+ flags -> {
+ assertTrue(flags.isPrivate());
+ assertTrue(flags.isStatic());
+ flags.promoteToPublic();
+ })
+ .transform());
+ }
+
+ @Test
+ public void testJVM() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getProgramClassData())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getProgramClassData())
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ // TODO(b/182335909): Ideally, this should also throw ICCE when desugaring.
+ .applyIf(
+ !parameters.canUseDefaultAndStaticInterfaceMethodsWhenDesugaring()
+ || parameters.isDexRuntimeVersion(Version.V7_0_0),
+ r -> r.assertSuccessWithOutput(EXPECTED_INVALID),
+ r -> r.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getProgramClassData())
+ .addKeepAllClassesRule()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ new B().m();
+ }
+ }
+
+ interface I {
+
+ default void m() {
+ System.out.println("I.m()");
+ }
+ }
+
+ public static class A {
+
+ private static /* will be: public static */ void m() {
+ System.out.println("A.m()");
+ }
+ }
+
+ static class B extends A implements I {}
+}
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionTest.java
new file mode 100644
index 0000000..c442b75
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithPublicStaticResolutionTest.java
@@ -0,0 +1,108 @@
+// 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.desugaring.interfacemethods;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DefaultInterfaceMethodDesugaringWithPublicStaticResolutionTest extends TestBase {
+
+ private static final String EXPECTED = StringUtils.lines("I.m()");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DefaultInterfaceMethodDesugaringWithPublicStaticResolutionTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ private Collection<Class<?>> getProgramClasses() {
+ return ImmutableList.of(TestClass.class, I.class, B.class);
+ }
+
+ private Collection<byte[]> getProgramClassData() throws Exception {
+ return ImmutableList.of(
+ transformer(A.class)
+ .setAccessFlags(
+ A.class.getDeclaredMethod("m"),
+ flags -> {
+ assertTrue(flags.isPrivate());
+ assertTrue(flags.isStatic());
+ flags.promoteToPublic();
+ })
+ .transform());
+ }
+
+ @Test
+ public void testJVM() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getProgramClassData())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getProgramClassData())
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getProgramClasses())
+ .addProgramClassFileData(getProgramClassData())
+ .addKeepAllClassesRule()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ I b = new B();
+ b.m();
+ }
+ }
+
+ interface I {
+
+ default void m() {
+ System.out.println("I.m()");
+ }
+ }
+
+ public static class A {
+
+ private static /* will be: public static */ void m() {
+ System.out.println("A.m()");
+ }
+ }
+
+ static class B extends A implements I {}
+}
diff --git a/src/test/java/com/android/tools/r8/dump/DumpMainDexInputsTest.java b/src/test/java/com/android/tools/r8/dump/DumpMainDexInputsTest.java
index 7c8eafe..1d01be7 100644
--- a/src/test/java/com/android/tools/r8/dump/DumpMainDexInputsTest.java
+++ b/src/test/java/com/android/tools/r8/dump/DumpMainDexInputsTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.dump;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -12,7 +13,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -89,19 +89,32 @@
"pre-native-multidex only",
parameters.getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.K));
Path dumpDir = temp.newFolder().toPath();
+ // Pre-compile to DEX and do main-dex list on DEX inputs only.
+ Path dexed =
+ testForD8()
+ .addInnerClasses(DumpMainDexInputsTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .writeToZip();
+
testForD8()
+ .addProgramFiles(dexed)
.setMinApi(parameters.getApiLevel())
- .addInnerClasses(DumpMainDexInputsTest.class)
.addMainDexListFiles(
mainDexListForMainDexFile1AndMainDexFile2(), mainDexListForMainDexFile3())
.addMainDexListClasses(MainDexClass1.class, MainDexClass2.class, TestClass.class)
- .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
.addOptionsModification(options -> options.dumpInputToDirectory = dumpDir.toString())
- .compile()
- .assertAllInfoMessagesMatch(containsString("Dumped compilation inputs to:"))
- .assertAllWarningMessagesMatch(
- containsString(
- "Dumping main dex list resources may have side effects due to I/O on Paths."))
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertNoErrors()
+ .assertInfosMatch(
+ diagnosticMessage(containsString("Dumped compilation inputs to:")))
+ .assertWarningsMatch(
+ diagnosticMessage(
+ containsString(
+ "Dumping main dex list resources may have side effects due to I/O"
+ + " on Paths."))))
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutputLines("Hello, world");
verifyDumpDir(dumpDir, true);
@@ -117,7 +130,7 @@
.setMinApi(parameters.getApiLevel())
.addInnerClasses(DumpMainDexInputsTest.class)
.addMainDexRulesFiles(newMainDexRulesPath1(), newMainDexRulesPath2())
- .addMainDexListClasses(MainDexClass1.class, MainDexClass2.class, TestClass.class)
+ .addMainDexKeepClassRules(MainDexClass1.class, MainDexClass2.class, TestClass.class)
.addOptionsModification(options -> options.dumpInputToDirectory = dumpDir.toString())
.compile()
.assertAllInfoMessagesMatch(containsString("Dumped compilation inputs to:"))
@@ -136,7 +149,7 @@
.setMinApi(parameters.getApiLevel())
.addInnerClasses(DumpMainDexInputsTest.class)
.addMainDexRuleFiles(newMainDexRulesPath1(), newMainDexRulesPath2())
- .addMainDexListClasses(MainDexClass1.class, MainDexClass2.class, TestClass.class)
+ .addMainDexKeepClassRules(MainDexClass1.class, MainDexClass2.class, TestClass.class)
.addOptionsModification(options -> options.dumpInputToDirectory = dumpDir.toString())
.addKeepAllClassesRule()
.allowDiagnosticMessages()
@@ -168,9 +181,10 @@
assertTrue(Files.exists(unzipped.resolve("r8-version")));
assertTrue(Files.exists(unzipped.resolve("program.jar")));
assertTrue(Files.exists(unzipped.resolve("library.jar")));
- assertTrue(Files.exists(unzipped.resolve("main-dex-list.txt")));
if (checkMainDexList) {
- String mainDex = new String(Files.readAllBytes(unzipped.resolve("main-dex-list.txt")));
+ Path mainDexListFile = unzipped.resolve("main-dex-list.txt");
+ assertTrue(Files.exists(mainDexListFile));
+ String mainDex = new String(Files.readAllBytes(mainDexListFile));
List<String> mainDexLines =
Arrays.stream(mainDex.split("\n")).filter(s -> !s.isEmpty()).collect(toList());
assertEquals(6, mainDexLines.size());
@@ -186,7 +200,9 @@
.collect(toList());
assertEquals(expected, mainDexLines);
} else {
- String mainDexRules = new String(Files.readAllBytes(unzipped.resolve("main-dex-rules.txt")));
+ Path mainDexRulesFile = unzipped.resolve("main-dex-rules.txt");
+ assertTrue(Files.exists(mainDexRulesFile));
+ String mainDexRules = new String(Files.readAllBytes(mainDexRulesFile));
assertThat(mainDexRules, containsString(mainDexRulesForMainDexFile1AndMainDexFile2));
assertThat(mainDexRules, containsString(mainDexRulesForMainDexFile3));
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingClassStaticizerTest.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingClassStaticizerTest.java
index 1e5bd5b..750c6fe 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingClassStaticizerTest.java
@@ -76,7 +76,7 @@
MethodSubject method =
codeInspector.clazz(CompanionHost.class).uniqueMethodWithName(renamedMethodName);
assertThat(method, isPresent());
- assertEquals("int", method.getMethod().method.proto.parameters.toString());
+ assertEquals("int", method.getMethod().getReference().proto.parameters.toString());
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/graph/InvokeSuperTest.java b/src/test/java/com/android/tools/r8/graph/InvokeSuperTest.java
index 1abfea6f..644fc9c 100644
--- a/src/test/java/com/android/tools/r8/graph/InvokeSuperTest.java
+++ b/src/test/java/com/android/tools/r8/graph/InvokeSuperTest.java
@@ -60,7 +60,8 @@
String getExpectedOutput() {
if (parameters.isDexRuntime()) {
Version version = parameters.getRuntime().asDex().getVm().getVersion();
- if (version.isAtLeast(Version.V5_1_1) && version.isOlderThanOrEqual(Version.V6_0_1)) {
+ if (version.isNewerThanOrEqual(Version.V5_1_1)
+ && version.isOlderThanOrEqual(Version.V6_0_1)) {
return UNEXPECTED_DEX_5_AND_6_OUTPUT;
}
}
diff --git a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
index b1d9990..06666db 100644
--- a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
@@ -227,7 +227,7 @@
DexField aFieldOnInterface = factory
.createField(factory.createType("LInterface;"), factory.intType, "aField");
- assertEquals(aFieldOnInterface, appInfo.lookupStaticTarget(aFieldOnSubClass).field);
+ assertEquals(aFieldOnInterface, appInfo.lookupStaticTarget(aFieldOnSubClass).getReference());
assertEquals("42", runArt(application));
diff --git a/src/test/java/com/android/tools/r8/graph/invokevirtual/InvokeVirtualPrivateBaseWithDefaultDirectInvokeTest.java b/src/test/java/com/android/tools/r8/graph/invokevirtual/InvokeVirtualPrivateBaseWithDefaultDirectInvokeTest.java
new file mode 100644
index 0000000..f989728
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/invokevirtual/InvokeVirtualPrivateBaseWithDefaultDirectInvokeTest.java
@@ -0,0 +1,111 @@
+// 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.graph.invokevirtual;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NoVerticalClassMerging;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.utils.AndroidApiLevel;
+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 InvokeVirtualPrivateBaseWithDefaultDirectInvokeTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public InvokeVirtualPrivateBaseWithDefaultDirectInvokeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ parameters.isCfRuntime(CfVm.JDK11),
+ r -> r.assertSuccessWithOutputLines("I::foo"),
+ r -> r.assertFailureWithErrorThatThrows(IllegalAccessError.class));
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .apply(this::assertResultIsCorrect);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepClassAndMembersRules(I.class)
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ // TODO(b/182189123): This should have the same behavior as D8.
+ .assertSuccessWithOutputLines("I::foo");
+ }
+
+ public void assertResultIsCorrect(SingleTestRunResult<?> result) {
+ if (parameters.isCfRuntime(CfVm.JDK11)
+ && parameters.getApiLevel().isGreaterThan(AndroidApiLevel.M)) {
+ result.assertSuccessWithOutputLines("I::foo");
+ return;
+ }
+ // TODO(b/152199517): Should be illegal access for DEX.
+ if (parameters.isDexRuntime() && parameters.getApiLevel().isGreaterThan(AndroidApiLevel.M)) {
+ result.assertSuccessWithOutputLines("I::foo");
+ return;
+ }
+ result.assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ }
+
+ @NoVerticalClassMerging
+ public interface I {
+
+ default void foo() {
+ System.out.println("I::foo");
+ }
+ }
+
+ @NoVerticalClassMerging
+ public static class Base {
+
+ private void foo() {
+ System.out.println("Base::foo");
+ }
+ }
+
+ public static class Sub extends Base implements I {}
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ runFoo(new Sub());
+ }
+
+ private static void runFoo(I i) {
+ i.foo();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/graph/invokevirtual/InvokeVirtualPrivateBaseWithDefaultTest.java b/src/test/java/com/android/tools/r8/graph/invokevirtual/InvokeVirtualPrivateBaseWithDefaultTest.java
new file mode 100644
index 0000000..9c9926d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/invokevirtual/InvokeVirtualPrivateBaseWithDefaultTest.java
@@ -0,0 +1,98 @@
+// 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.graph.invokevirtual;
+
+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.android.tools.r8.utils.AndroidApiLevel;
+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 InvokeVirtualPrivateBaseWithDefaultTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public InvokeVirtualPrivateBaseWithDefaultTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ parameters.isCfRuntime()
+ || parameters.getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.M),
+ r -> r.assertFailureWithErrorThatThrows(IllegalAccessError.class),
+ // TODO(b/152199517): Should be illegal access for DEX.
+ r -> r.assertSuccessWithOutputLines("I::foo"));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepClassAndMembersRules(I.class)
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ parameters.isCfRuntime()
+ || parameters.getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.M),
+ r -> r.assertFailureWithErrorThatThrows(IllegalAccessError.class),
+ // TODO(b/152199517): Should be illegal access for DEX.
+ r -> r.assertSuccessWithOutputLines("I::foo"));
+ }
+
+ @NoVerticalClassMerging
+ public interface I {
+
+ default void foo() {
+ System.out.println("I::foo");
+ }
+ }
+
+ @NoVerticalClassMerging
+ public static class Base {
+
+ private void foo() {
+ System.out.println("Base::foo");
+ }
+ }
+
+ public static class Sub extends Base implements I {}
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ new Sub().foo();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
index 51b5323..57078d1 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
@@ -70,12 +70,13 @@
private void testVirtualLookup(DexProgramClass clazz, DexEncodedMethod method) {
// Check lookup will produce the same result.
- DexMethod id = method.method;
+ DexMethod id = method.getReference();
assertEquals(
- appInfo().resolveMethodOnClass(method.method, id.holder).getSingleTarget(), method);
+ appInfo().resolveMethodOnClass(method.getReference(), id.holder).getSingleTarget(), method);
// Check lookup targets with include method.
- ResolutionResult resolutionResult = appInfo().resolveMethodOnClass(method.method, clazz);
+ ResolutionResult resolutionResult =
+ appInfo().resolveMethodOnClass(method.getReference(), clazz);
AppInfoWithLiveness appInfo = null; // TODO(b/154881041): Remove or compute liveness.
LookupResult lookupResult =
resolutionResult.lookupVirtualDispatchTargets(
@@ -96,7 +97,7 @@
AppInfoWithLiveness appInfo = null; // TODO(b/154881041): Remove or compute liveness.
LookupResultSuccess lookupResult =
appInfo()
- .resolveMethodOnInterface(clazz, method.method)
+ .resolveMethodOnInterface(clazz, method.getReference())
.lookupVirtualDispatchTargets(clazz, appInfo(), appInfo, dexReference -> false)
.asLookupResultSuccess();
assertNotNull(lookupResult);
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
index 024dd38..ec665d3 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
@@ -140,7 +140,7 @@
private DexEncodedField uniqueFieldByName(DexProgramClass clazz, String name) {
DexEncodedField result = null;
for (DexEncodedField field : clazz.fields()) {
- if (field.field.name.toSourceString().equals(name)) {
+ if (field.getReference().name.toSourceString().equals(name)) {
assertNull(result);
result = field;
}
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java b/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java
index 009d4e3d..36acfe9 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java
@@ -137,7 +137,7 @@
private Node findNode(Iterable<Node> nodes, String name) {
for (Node n : nodes) {
- if (n.getMethod().method.name.toString().equals(name)) {
+ if (n.getMethod().getReference().name.toString().equals(name)) {
return n;
}
}
@@ -147,7 +147,7 @@
private ProgramMethod findMethod(String name) {
for (DexProgramClass clazz : appView.appInfo().classes()) {
for (DexEncodedMethod method : clazz.methods()) {
- if (method.method.name.toString().equals(name)) {
+ if (method.getReference().name.toString().equals(name)) {
return new ProgramMethod(clazz, method);
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java
index a3bd157..bc84108 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java
@@ -62,4 +62,15 @@
CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
return Integer.parseInt(s.subSequence(beginIndex, endIndex).toString(), radix);
}
+
+ public static int parseIntSubsequenceWithRadixDalvik(
+ CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
+ // Dalvik (API level 19 and below) does not support a '+' prefix.
+ if (endIndex - beginIndex >= 2
+ && s.charAt(beginIndex) == '+'
+ && Character.digit(s.charAt(beginIndex + 1), radix) >= 0) {
+ beginIndex++;
+ }
+ return Integer.parseInt(s.subSequence(beginIndex, endIndex).toString(), radix);
+ }
}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java
index 65a60ef..089fa86 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java
@@ -15,6 +15,17 @@
return Long.parseLong(s.subSequence(beginIndex, endIndex).toString(), radix);
}
+ public static long parseLongSubsequenceWithRadixDalvik(
+ CharSequence s, int beginIndex, int endIndex, int radix) {
+ // Dalvik (API level 19 and below) does not support a '+' prefix.
+ if (endIndex - beginIndex >= 2
+ && s.charAt(beginIndex) == '+'
+ && Character.digit(s.charAt(beginIndex + 1), radix) >= 0) {
+ beginIndex++;
+ }
+ return Long.parseLong(s.subSequence(beginIndex, endIndex).toString(), radix);
+ }
+
public static long divideUnsigned(long dividend, long divisor) {
// This implementation is adapted from Guava's UnsignedLongs.java and Longs.java.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index 7049089..aad2f6f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -276,7 +276,7 @@
for (int i = 0; i < 3; ++i) {
MethodSubject markerSubject = clazz.method("void", "marker" + i, Collections.emptyList());
assertTrue(markerSubject.isPresent());
- markers[i] = markerSubject.getMethod().method;
+ markers[i] = markerSubject.getMethod().getReference();
}
// Count invokes to callee between markers.
@@ -290,7 +290,7 @@
DexMethod target = ((InvokeInstructionSubject) instruction).invokedMethod();
- if (target == callee.getMethod().method) {
+ if (target == callee.getMethod().getReference()) {
assertTrue(phase == 0 || phase == 1);
++counters[phase];
continue;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EnumCanonicalizationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EnumCanonicalizationTest.java
index 589fa3f..709a44b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EnumCanonicalizationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/EnumCanonicalizationTest.java
@@ -73,7 +73,7 @@
.streamInstructions()
.filter(InstructionSubject::isStaticGet)
.map(InstructionSubject::getField)
- .filter(enumFieldSubject.getField().field::equals)
+ .filter(enumFieldSubject.getField().getReference()::equals)
.count());
assertEquals(
1,
@@ -81,7 +81,9 @@
.streamInstructions()
.filter(InstructionSubject::isStaticGet)
.map(InstructionSubject::getField)
- .filter(enumWithClassInitializationSideEffectsFieldSubject.getField().field::equals)
+ .filter(
+ enumWithClassInitializationSideEffectsFieldSubject.getField().getReference()
+ ::equals)
.count());
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java
new file mode 100644
index 0000000..b3ca988
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java
@@ -0,0 +1,113 @@
+// 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.
+
+package com.android.tools.r8.ir.optimize.devirtualize;
+
+import com.android.tools.r8.NeverClassInline;
+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.TestRunResult;
+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 PackagePrivateOverrideDeVirtualizerTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final String[] EXPECTED = new String[] {"SubViewModel.clear()", "ViewModel.clear()"};
+ private final String[] EXPECTED_DALVIK =
+ new String[] {"SubViewModel.clear()", "SubViewModel.clear()"};
+ private final String NEW_DESCRIPTOR = "Lfoo/bar/baz/SubViewModel;";
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PackagePrivateOverrideDeVirtualizerTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
+ .addProgramClasses(ViewModel.class)
+ .addProgramClassFileData(
+ getSubViewModelInAnotherPackage(), getRewrittenSubViewModelInMain())
+ .run(parameters.getRuntime(), Main.class)
+ .apply(this::assertSuccessOutput);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(ViewModel.class)
+ .addProgramClassFileData(
+ getSubViewModelInAnotherPackage(), getRewrittenSubViewModelInMain())
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableInliningAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .run(parameters.getRuntime(), Main.class)
+ // TODO(b/182185057): This should be EXPECTED.
+ .assertSuccessWithOutputLines(EXPECTED_DALVIK);
+ }
+
+ private byte[] getSubViewModelInAnotherPackage() throws Exception {
+ return transformer(SubViewModel.class).setClassDescriptor(NEW_DESCRIPTOR).transform();
+ }
+
+ private byte[] getRewrittenSubViewModelInMain() throws Exception {
+ return transformer(Main.class)
+ .replaceClassDescriptorInMethodInstructions(descriptor(SubViewModel.class), NEW_DESCRIPTOR)
+ .transform();
+ }
+
+ private void assertSuccessOutput(TestRunResult<?> result) {
+ if (parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik()) {
+ result.assertSuccessWithOutputLines(EXPECTED_DALVIK);
+ } else {
+ result.assertSuccessWithOutputLines(EXPECTED);
+ }
+ }
+
+ @SuppressWarnings("override") /* after changing the package the clear method is not overridden */
+ @NoVerticalClassMerging
+ public static class ViewModel {
+
+ @NeverInline
+ void clear() {
+ System.out.println("ViewModel.clear()");
+ }
+ }
+
+ @NeverClassInline
+ @SuppressWarnings("override") /* after changing the package the clear method is not overridden */
+ public static class /* foo.bar.baz. */ SubViewModel extends ViewModel {
+
+ @NeverInline
+ public void clear() {
+ System.out.println("SubViewModel.clear()");
+ }
+
+ public void callBridge() {
+ clear();
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ SubViewModel viewModel = new SubViewModel();
+ viewModel.callBridge();
+ ((ViewModel) viewModel).clear();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java
index 50e52e2..fb3d7e4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java
@@ -84,7 +84,7 @@
mainMethodSubject
.streamInstructions()
.filter(InstructionSubject::isStaticGet)
- .anyMatch(x -> x.getField() == clinitFieldSubject.getField().field));
+ .anyMatch(x -> x.getField() == clinitFieldSubject.getField().getReference()));
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalInstanceFieldLoadAfterStoreTest.java b/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalInstanceFieldLoadAfterStoreTest.java
index 329e574..cad2c50 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalInstanceFieldLoadAfterStoreTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalInstanceFieldLoadAfterStoreTest.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ir.optimize.redundantfieldloadelimination.RedundantFinalStaticFieldLoadAfterStoreTest.A;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
@@ -80,7 +79,7 @@
.streamInstructions()
.filter(InstructionSubject::isInstanceGet)
.map(InstructionSubject::getField)
- .filter(fieldSubject.getField().field::equals)
+ .filter(fieldSubject.getField().getReference()::equals)
.count();
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalStaticFieldLoadAfterStoreTest.java b/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalStaticFieldLoadAfterStoreTest.java
index 2b910f5..701c43f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalStaticFieldLoadAfterStoreTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/redundantfieldloadelimination/RedundantFinalStaticFieldLoadAfterStoreTest.java
@@ -77,7 +77,7 @@
.streamInstructions()
.filter(InstructionSubject::isStaticGet)
.map(InstructionSubject::getField)
- .filter(fieldSubject.getField().field::equals)
+ .filter(fieldSubject.getField().getReference()::equals)
.count();
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
index 6e91c38..d268888 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
@@ -345,7 +345,7 @@
assertThat(clazz, isPresent());
return Streams.stream(clazz.getDexProgramClass().methods())
.filter(method -> !method.isStatic())
- .map(method -> method.method.toSourceString())
+ .map(method -> method.getReference().toSourceString())
.sorted()
.collect(Collectors.toList());
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
index b254b43..0125189 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
@@ -64,7 +64,7 @@
MethodSubject createStaticMethodSubject =
factoryClassSubject.uniqueMethodWithName("createStatic");
assertThat(createStaticMethodSubject, isPresent());
- assertEquals(1, createStaticMethodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(1, createStaticMethodSubject.getMethod().getReference().proto.parameters.size());
for (int i = 1; i <= 3; ++i) {
String createStaticWithUnusedMethodName = "createStaticWithUnused" + i;
@@ -72,7 +72,7 @@
factoryClassSubject.uniqueMethodWithName(createStaticWithUnusedMethodName);
assertThat(createStaticWithUnusedMethodSubject, isPresent());
- DexMethod method = createStaticWithUnusedMethodSubject.getMethod().method;
+ DexMethod method = createStaticWithUnusedMethodSubject.getMethod().getReference();
assertEquals(1, method.proto.parameters.size());
assertEquals("java.lang.String", method.proto.parameters.toString());
}
@@ -81,7 +81,7 @@
factoryClassSubject.uniqueMethodWithName("createStaticWithUnused4");
assertThat(createStaticWithUnusedMethodSubject, isPresent());
- DexMethod method = createStaticWithUnusedMethodSubject.getMethod().method;
+ DexMethod method = createStaticWithUnusedMethodSubject.getMethod().getReference();
assertEquals(3, method.proto.parameters.size());
assertEquals(
"java.lang.String java.lang.String java.lang.String", method.proto.parameters.toString());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java
index 0de94c9..8dc29fb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/PrivateInstanceMethodCollisionTest.java
@@ -81,7 +81,7 @@
assertEquals(2, aClassSubject.allMethods(FoundMethodSubject::isVirtual).size());
String name = null;
for (FoundMethodSubject m : aClassSubject.allMethods(FoundMethodSubject::isVirtual)) {
- assertEquals(1, m.getMethod().method.proto.parameters.size());
+ assertEquals(1, m.getMethod().getReference().proto.parameters.size());
if (name == null) {
name = m.getFinalName();
} else {
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 c6dfe83..2e3904a 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
@@ -95,7 +95,7 @@
// TODO(b/131735725): Should also remove arguments from the virtual methods.
if (keepUninstantiatedArguments || methodSubject.getOriginalName().contains("Virtual")) {
- assertEquals(3, methodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(3, methodSubject.getMethod().getReference().proto.parameters.size());
assertEquals(3, methodSubject.getMethod().parameterAnnotationsList.size());
for (int i = 0; i < 3; ++i) {
@@ -115,7 +115,7 @@
}
}
} else {
- assertEquals(2, methodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(2, methodSubject.getMethod().getReference().proto.parameters.size());
assertEquals(2, methodSubject.getMethod().parameterAnnotationsList.size());
for (int i = 0; i < 2; ++i) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java
index 0ac4efc..5e5345a 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java
@@ -63,16 +63,16 @@
MethodSubject createStaticMethodSubject =
factoryClassSubject.uniqueMethodWithName("createStatic");
assertThat(createStaticMethodSubject, isPresent());
- assertTrue(createStaticMethodSubject.getMethod().method.proto.returnType.isVoidType());
+ assertTrue(createStaticMethodSubject.getMethod().getReference().proto.returnType.isVoidType());
MethodSubject createVirtualMethodSubject =
factoryClassSubject.uniqueMethodWithName("createVirtual");
assertThat(createVirtualMethodSubject, isPresent());
- assertTrue(createVirtualMethodSubject.getMethod().method.proto.returnType.isVoidType());
+ assertTrue(createVirtualMethodSubject.getMethod().getReference().proto.returnType.isVoidType());
createVirtualMethodSubject =
inspector.clazz(SubFactory.class).uniqueMethodWithName("createVirtual");
assertThat(createVirtualMethodSubject, isPresent());
- assertTrue(createVirtualMethodSubject.getMethod().method.proto.returnType.isVoidType());
+ assertTrue(createVirtualMethodSubject.getMethod().getReference().proto.returnType.isVoidType());
ClassSubject subSubFactoryClassSubject = inspector.clazz(SubSubFactory.class);
assertThat(subSubFactoryClassSubject.method("void", "createVirtual"), isPresent());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java
index 45d858d..14efc77 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/CollisionWithLibraryMethodsTest.java
@@ -65,10 +65,10 @@
if (minification) {
assertEquals("a", methodSubject.getFinalName());
- assertEquals(0, methodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(0, methodSubject.getMethod().getReference().proto.parameters.size());
} else {
assertEquals("toString1", methodSubject.getFinalName());
- assertEquals(0, methodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(0, methodSubject.getMethod().getReference().proto.parameters.size());
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java
index 073c3b4..b7ddd9e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/PrivateInstanceMethodCollisionTest.java
@@ -79,7 +79,7 @@
assertEquals(2, aClassSubject.allMethods(FoundMethodSubject::isVirtual).size());
String name = null;
for (FoundMethodSubject m : aClassSubject.allMethods(FoundMethodSubject::isVirtual)) {
- assertEquals(1, m.getMethod().method.proto.parameters.size());
+ assertEquals(1, m.getMethod().getReference().proto.parameters.size());
if (name == null) {
name = m.getFinalName();
} else {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java
index af6296b..138f0a9 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAndUninstantiatedTypesTest.java
@@ -58,8 +58,8 @@
List<FoundMethodSubject> methods = i.clazz(Main.class).allMethods();
assertEquals(9, methods.size());
for (FoundMethodSubject method : methods) {
- if (!method.getMethod().method.name.toString().equals("main")) {
- assertEquals(0, method.getMethod().method.getArity());
+ if (!method.getMethod().getReference().name.toString().equals("main")) {
+ assertEquals(0, method.getMethod().getReference().getArity());
}
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java
index bd1b805..955c5d4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedAnnotatedArgumentsTest.java
@@ -91,7 +91,7 @@
assertThat(methodSubject, isPresent());
if (keepUnusedArguments) {
- assertEquals(3, methodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(3, methodSubject.getMethod().getReference().proto.parameters.size());
assertEquals(3, methodSubject.getMethod().parameterAnnotationsList.size());
for (int i = 0; i < 3; ++i) {
@@ -109,7 +109,7 @@
}
}
} else {
- assertEquals(2, methodSubject.getMethod().method.proto.parameters.size());
+ assertEquals(2, methodSubject.getMethod().getReference().proto.parameters.size());
assertEquals(2, methodSubject.getMethod().parameterAnnotationsList.size());
for (int i = 0; i < 2; ++i) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java
index 7456d35..281db3e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentRemovalWithOverridingTest.java
@@ -63,7 +63,8 @@
MethodSubject methodSubject = classSubject.uniqueMethodWithName("greeting");
assertThat(methodSubject, isPresent());
- assertEquals("java.lang.String", methodSubject.getMethod().method.proto.parameters.toString());
+ assertEquals(
+ "java.lang.String", methodSubject.getMethod().getReference().proto.parameters.toString());
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java
index 2c7fe55..1137a01 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsCollisionTest.java
@@ -85,7 +85,7 @@
MethodSubject methodB1Subject =
bClassSubject.allMethods().stream().filter(FoundMethodSubject::isStatic).findFirst().get();
assertThat(methodB1Subject, isPresent());
- assertEquals(0, methodB1Subject.getMethod().method.proto.parameters.size());
+ assertEquals(0, methodB1Subject.getMethod().getReference().proto.parameters.size());
// TODO(b/129933280): Determine if we should use member pool collection for unused argument
// removal for private and static methods.
@@ -97,7 +97,7 @@
MethodSubject methodB2Subject =
bClassSubject.allMethods().stream().filter(FoundMethodSubject::isVirtual).findFirst().get();
assertThat(methodB2Subject, isPresent());
- assertEquals(0, methodB2Subject.getMethod().method.proto.parameters.size());
+ assertEquals(0, methodB2Subject.getMethod().getReference().proto.parameters.size());
// Verify that the virtual method B.method2() does not collide with a method in A.
assertNotEquals(methodB2Subject.getFinalName(), methodA1Subject.getFinalName());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
index ea67170..c890e97 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
@@ -59,7 +59,7 @@
MethodSubject methodSubject = classSubject.uniqueMethodWithName("<init>");
assertThat(methodSubject, isPresent());
- assertTrue(methodSubject.getMethod().method.proto.parameters.isEmpty());
+ assertTrue(methodSubject.getMethod().getReference().proto.parameters.isEmpty());
assertThat(inspector.clazz(B.class), not(isPresent()));
assertThat(inspector.clazz(C.class), not(isPresent()));
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
index 23c4628..7f41f05 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
@@ -213,9 +213,14 @@
String returnType,
String... lines) {
StringBuilder builder = new StringBuilder();
- builder.append(".method ").append(access).append(" ").append(name)
- .append(StringUtils.join(argumentTypes, "", BraceType.PARENS))
- .append(returnType).append("\n");
+ builder
+ .append(".method ")
+ .append(access)
+ .append(" ")
+ .append(name)
+ .append(StringUtils.join("", argumentTypes, BraceType.PARENS))
+ .append(returnType)
+ .append("\n");
for (String line : lines) {
builder.append(line).append("\n");
}
@@ -382,7 +387,7 @@
}
builder
.append(name)
- .append(StringUtils.join(argumentTypes, "", BraceType.PARENS))
+ .append(StringUtils.join("", argumentTypes, BraceType.PARENS))
.append(returnType)
.append(System.lineSeparator());
builder.append(".limit locals ").append(localsLimit).append(System.lineSeparator());
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
index ab2d643..73f7a6f 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
@@ -219,7 +219,7 @@
List<String> args = new ArrayList<>();
args.add("--output=" + dex.toString());
args.add(classes.toString());
- System.out.println("running: dx " + StringUtils.join(args, " "));
+ System.out.println("running: dx " + StringUtils.join(" ", args));
return ToolHelper.runDX(args.toArray(new String[args.size()]));
}
diff --git a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
index d21bd3a..a831fb0 100644
--- a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
+++ b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
@@ -70,7 +70,7 @@
}
static boolean isAndroidKOrAbove(DexVm dexVm, Tool tool) {
- return dexVm.getVersion().isAtLeast(Version.V4_4_4);
+ return dexVm.getVersion().isNewerThanOrEqual(Version.V4_4_4);
}
static boolean isAndroidLOrAbove(DexVm dexVm, Tool tool) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java
index b76eaa0..872b5f0 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java
@@ -129,7 +129,7 @@
MethodSubject method = main.uniqueMethodWithName(methodName);
assertThat(method, isPresent());
- int arity = method.getMethod().method.getArity();
+ int arity = method.getMethod().getReference().getArity();
// One from the method's own argument, if any, and
// Two from Array utils, `contains` and `indexOf`, if inlined with access relaxation.
assertEquals(
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinUnusedArgumentsInLambdasTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinUnusedArgumentsInLambdasTest.java
index 4db441f..19458e2 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinUnusedArgumentsInLambdasTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinUnusedArgumentsInLambdasTest.java
@@ -52,7 +52,7 @@
MethodSubject invoke = classSubject.uniqueMethodWithName("invoke");
assertThat(invoke, isPresent());
- assertEquals(2, invoke.getMethod().method.proto.parameters.size());
+ assertEquals(2, invoke.getMethod().getReference().proto.parameters.size());
}
}));
}
@@ -68,7 +68,7 @@
if (classSubject.getOriginalDescriptor().contains("$js")) {
MethodSubject get = classSubject.uniqueMethodWithName("get");
assertThat(get, isPresent());
- assertEquals(3, get.getMethod().method.proto.parameters.size());
+ assertEquals(3, get.getMethod().getReference().proto.parameters.size());
}
}));
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexDevirtualizerTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexDevirtualizerTest.java
index 6cb7ab4..ad0cf84 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexDevirtualizerTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexDevirtualizerTest.java
@@ -79,13 +79,16 @@
});
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void testMainDexClasses() throws Exception {
assumeTrue(parameters.isDexRuntime());
assumeTrue(parameters.getDexRuntimeVersion().isDalvik());
runTest(
r8FullTestBuilder ->
- r8FullTestBuilder.addMainDexListClasses(I.class, Provider.class, Main.class),
+ r8FullTestBuilder
+ .addMainDexListClasses(I.class, Provider.class, Main.class)
+ .allowDiagnosticWarningMessages(),
this::inspect);
}
@@ -94,7 +97,7 @@
assumeTrue(parameters.isDexRuntime());
assumeTrue(parameters.getDexRuntimeVersion().isDalvik());
runTest(
- r8FullTestBuilder -> r8FullTestBuilder.addMainDexClassRules(Main.class, I.class),
+ r8FullTestBuilder -> r8FullTestBuilder.addMainDexKeepClassRules(Main.class, I.class),
this::inspect);
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningSpuriousRootTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningSpuriousRootTest.java
index 5f21fee..3290031 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningSpuriousRootTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningSpuriousRootTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.maindexlist;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -15,6 +16,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -59,6 +61,7 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void test() throws Exception {
// The generated main dex list should contain Main (which is a root) and A (which is a direct
@@ -82,7 +85,13 @@
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
.noMinification()
- .compile();
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)));
CodeInspector inspector = compileResult.inspector();
ClassSubject mainClassSubject = inspector.clazz(Main.class);
assertThat(mainClassSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningTest.java
index 98ec426..013fdd3 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.maindexlist;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -16,6 +17,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -61,6 +63,7 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void test() throws Exception {
// The generated main dex list should contain Main (which is a root) and A (which is a direct
@@ -80,7 +83,13 @@
.enableNoHorizontalClassMergingAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .compile();
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)));
CodeInspector inspector = compileResult.inspector();
ClassSubject mainClassSubject = inspector.clazz(Main.class);
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningWithTracingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningWithTracingTest.java
index f5971f9..bb3b81c 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningWithTracingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainDexInliningWithTracingTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.maindexlist;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -16,6 +17,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -61,6 +63,7 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void test() throws Exception {
// The generated main dex list should contain Main (which is a root) and A (which is a direct
@@ -84,7 +87,13 @@
.enableNoHorizontalClassMergingAnnotations()
.noMinification()
.setMinApi(parameters.getApiLevel())
- .compile();
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)));
CodeInspector inspector = compileResult.inspector();
ClassSubject mainClassSubject = inspector.clazz(Main.class);
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainHorizontalMergingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainHorizontalMergingTest.java
index c2c96ec..4d59d9b 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainHorizontalMergingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainHorizontalMergingTest.java
@@ -65,6 +65,7 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void testMainDexList() throws Exception {
assertEquals(3, mainDexList.size());
@@ -73,7 +74,9 @@
assertTrue(mainDexReferences.contains(A.class.getTypeName()));
assertTrue(mainDexReferences.contains(B.class.getTypeName()));
assertTrue(mainDexReferences.contains(Main.class.getTypeName()));
- runTest(builder -> builder.addMainDexListClassReferences(mainDexList));
+ runTest(
+ builder ->
+ builder.addMainDexListClassReferences(mainDexList).allowDiagnosticWarningMessages());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainVerticalMergingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainVerticalMergingTest.java
index ec50d1e..480abb7 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainVerticalMergingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListFromGenerateMainVerticalMergingTest.java
@@ -65,6 +65,7 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void testMainDexList() throws Exception {
assertEquals(3, mainDexList.size());
@@ -73,7 +74,9 @@
assertTrue(mainDexReferences.contains(A.class.getTypeName()));
assertTrue(mainDexReferences.contains(B.class.getTypeName()));
assertTrue(mainDexReferences.contains(Main.class.getTypeName()));
- runTest(builder -> builder.addMainDexListClassReferences(mainDexList));
+ runTest(
+ builder ->
+ builder.addMainDexListClassReferences(mainDexList).allowDiagnosticWarningMessages());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListInliningTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListInliningTest.java
index 09df9d4..731d0ec 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListInliningTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListInliningTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.maindexlist;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
@@ -14,6 +15,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
@@ -37,6 +39,7 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test should be converted to a main-dex-rules test.
@Test
public void test() throws Exception {
R8TestCompileResult compileResult =
@@ -47,7 +50,13 @@
.collectMainDexClasses()
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters.getApiLevel())
- .compile();
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)));
CodeInspector inspector = compileResult.inspector();
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListNoDirectDependenciesTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListNoDirectDependenciesTest.java
index 8f5d997..e72cc3e 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListNoDirectDependenciesTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListNoDirectDependenciesTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.maindexlist;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -11,6 +12,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
@@ -34,17 +36,24 @@
this.parameters = parameters;
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void test() throws Exception {
R8TestCompileResult compileResult =
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addMainDexListClasses(A.class)
- .addMainDexClassRules(B.class)
+ .addMainDexKeepClassRules(B.class)
.collectMainDexClasses()
.noTreeShaking()
.setMinApi(parameters.getApiLevel())
- .compile();
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)));
CodeInspector inspector = compileResult.inspector();
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexPrunedReferenceTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexPrunedReferenceTest.java
index e2d7dd2..c10a7a6 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexPrunedReferenceTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexPrunedReferenceTest.java
@@ -48,11 +48,12 @@
testMainDex(builder -> {}, Assert::assertNull);
}
+ // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@Test
public void testMainDexClassesList() throws Exception {
assumeTrue(parameters.getDexRuntimeVersion().isDalvik());
testMainDex(
- builder -> builder.addMainDexListClasses(Main.class),
+ builder -> builder.addMainDexListClasses(Main.class).allowDiagnosticWarningMessages(),
mainDexClasses -> assertEquals(ImmutableSet.of(Main.class.getTypeName()), mainDexClasses));
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java
index 8252f4d..16dc8db 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.maindexlist;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticOrigin;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
+import static org.hamcrest.CoreMatchers.allOf;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -11,11 +14,17 @@
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.nio.file.Files;
@@ -81,23 +90,67 @@
checkCompilationResult(compileResult);
}
+ @Test
+ public void testSupportedMainDexListD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ // It remains a supported mode to first compile to DEX and then use tracing on the compiled
+ // output. Neither the compilation, the trace or the merge should issue any diagnostics.
+ Path dexed =
+ testForD8()
+ .addInnerClasses(MainDexWithSynthesizedClassesTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertNoMessages)
+ .writeToZip();
+
+ Path mainDexFile = temp.newFile("maindex.list").toPath();
+ testForMainDexListGenerator()
+ .addLibraryFiles(ToolHelper.getFirstSupportedAndroidJar(parameters.getApiLevel()))
+ .addProgramFiles(dexed)
+ .addMainDexRules("-keep class " + typeName(TestClass.class) + "{ *; }")
+ .setMainDexListOutputPath(mainDexFile)
+ .run();
+
+ D8TestCompileResult compileResult =
+ testForD8()
+ .addProgramFiles(dexed)
+ .addMainDexListFiles(mainDexFile)
+ .setMinApi(parameters.getApiLevel())
+ .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertNoMessages);
+ checkCompilationResult(compileResult);
+ }
+
/**
* This test checks for maintained support of including synthetics from main-dex-list entries in
* the main-dex file. This test simulates that the tracing done at the class-file level has
* determined that TestClass and A are both traced. Thus the synthetic lambda from A will be
* included in the main-dex file.
*
- * <p>TODO(b/181858113): Remove once deprecated main-dex-list is removed.
+ * <p>TODO(b/181858113): Update to assert an error is raised once deprecated period is over.
*/
@Test
public void testDeprecatedSyntheticsFromMainDexListD8() throws Exception {
assumeTrue(parameters.isDexRuntime());
+ Path mainDexFile = temp.newFile("maindex.list").toPath();
+ FileUtils.writeTextFile(mainDexFile, binaryName(A.class) + ".class");
D8TestCompileResult compileResult =
testForD8()
.addInnerClasses(MainDexWithSynthesizedClassesTest.class)
- .addMainDexListClasses(TestClass.class, A.class)
+ .addMainDexListClasses(TestClass.class)
+ .addMainDexListFiles(mainDexFile)
.setMinApi(parameters.getApiLevel())
- .compile();
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ // The "classes" addition has no origin.
+ allOf(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class),
+ diagnosticOrigin(Origin.unknown())),
+ // The "file" addition must have the file origin.
+ allOf(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class),
+ diagnosticOrigin(new PathOrigin(mainDexFile)))));
checkCompilationResult(compileResult);
}
@@ -112,15 +165,31 @@
@Test
public void testDeprecatedSyntheticsFromMainDexListR8() throws Exception {
assumeTrue(parameters.isDexRuntime());
+ Path mainDexFile = temp.newFile("maindex.list").toPath();
+ FileUtils.writeTextFile(mainDexFile, binaryName(A.class) + ".class");
R8TestCompileResult compileResult =
testForR8(parameters.getBackend())
.addInnerClasses(MainDexWithSynthesizedClassesTest.class)
.setMinApi(parameters.getApiLevel())
.addOptionsModification(o -> o.minimalMainDex = true)
- .addMainDexListClasses(TestClass.class, A.class)
+ .addMainDexListClasses(TestClass.class)
+ .addMainDexListFiles(mainDexFile)
.noMinification()
.noTreeShaking()
- .compile();
+ .allowDiagnosticWarningMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ // The "classes" addition has no origin.
+ allOf(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class),
+ diagnosticOrigin(Origin.unknown())),
+ // The "file" addition must have the file origin.
+ allOf(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class),
+ diagnosticOrigin(new PathOrigin(mainDexFile)))));
checkCompilationResult(compileResult, compileResult.app);
}
@@ -128,7 +197,7 @@
checkCompilationResult(compileResult, compileResult.app);
}
- private void checkCompilationResult(TestCompileResult compileResult, AndroidApp app)
+ private void checkCompilationResult(TestCompileResult<?, ?> compileResult, AndroidApp app)
throws Exception {
if (parameters.getRuntime().asDex().getMinApiLevel().getLevel()
< nativeMultiDexLevel.getLevel()) {
diff --git a/src/test/java/com/android/tools/r8/maindexlist/warnings/MainDexWarningsTest.java b/src/test/java/com/android/tools/r8/maindexlist/warnings/MainDexWarningsTest.java
index 22bad85..19e75b3 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/warnings/MainDexWarningsTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/warnings/MainDexWarningsTest.java
@@ -56,7 +56,7 @@
.addProgramClasses(testClasses)
.addKeepMainRule(mainClass)
// Include main dex rule for class Static.
- .addMainDexClassRules(Main.class, Static.class)
+ .addMainDexKeepClassRules(Main.class, Static.class)
.enableForceInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.compile()
@@ -93,7 +93,7 @@
// Include explicit main dex entry for class Static.
.addMainDexListClasses(Main.class, Static.class)
// Include main dex rule for class Static2.
- .addMainDexClassRules(Static2.class)
+ .addMainDexKeepClassRules(Static2.class)
.addDontWarn(Static.class)
.allowDiagnosticWarningMessages()
.enableForceInliningAnnotations()
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingClassPathInterfaceInheritTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingClassPathInterfaceInheritTest.java
new file mode 100644
index 0000000..5270eab
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingClassPathInterfaceInheritTest.java
@@ -0,0 +1,84 @@
+// 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.naming.applymapping;
+
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.nio.file.Path;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+// This is a reproduction of b/181887416.
+public class ApplyMappingClassPathInterfaceInheritTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final boolean minifyLibrary;
+
+ @Parameters(name = "{0}, minifyLibrary: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ }
+
+ public ApplyMappingClassPathInterfaceInheritTest(
+ TestParameters parameters, boolean minifyLibrary) {
+ this.parameters = parameters;
+ this.minifyLibrary = minifyLibrary;
+ }
+
+ @Test
+ public void testApplyMapping() throws Exception {
+ R8TestCompileResult libraryResult =
+ testForR8(parameters.getBackend())
+ .addLibraryClasses(LibI.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .addProgramClasses(ClassPathI.class)
+ .applyIf(
+ minifyLibrary,
+ TestShrinkerBuilder::addKeepAllClassesRuleWithAllowObfuscation,
+ TestShrinkerBuilder::addKeepAllClassesRule)
+ .setMinApi(parameters.getApiLevel())
+ .compile();
+ Path libraryJar = libraryResult.writeToZip();
+ testForR8(parameters.getBackend())
+ .addLibraryClasses(LibI.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .addClasspathClasses(ClassPathI.class)
+ .addProgramClasses(Main.class)
+ .addKeepAllClassesRule()
+ .addApplyMapping(libraryResult.getProguardMap())
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .addRunClasspathClasses(LibI.class)
+ .addRunClasspathFiles(libraryJar)
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ minifyLibrary,
+ r -> r.assertSuccessWithOutputLines("a.a"),
+ r -> r.assertSuccessWithOutputLines(ClassPathI.class.getTypeName()));
+ }
+
+ public interface LibI {}
+
+ public interface ClassPathI extends LibI {}
+
+ public static class Main {
+
+ public static void main(String[] args) throws ClassNotFoundException {
+ System.out.println(
+ Class.forName(
+ "com.android.tools.r8.naming.applymapping"
+ + ".ApplyMappingClassPathInterfaceInheritTest$ClassPathI")
+ .getName());
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/b72391662/B72391662.java b/src/test/java/com/android/tools/r8/naming/b72391662/B72391662.java
index ddf20ef..c4c9fdf 100644
--- a/src/test/java/com/android/tools/r8/naming/b72391662/B72391662.java
+++ b/src/test/java/com/android/tools/r8/naming/b72391662/B72391662.java
@@ -104,7 +104,7 @@
}
private static boolean vmVersionIgnored() {
- return !ToolHelper.getDexVm().getVersion().isAtLeast(Version.V7_0_0);
+ return !ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(Version.V7_0_0);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java b/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java
index ff61668..5c48866 100644
--- a/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java
+++ b/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java
@@ -91,13 +91,13 @@
assertNotNull(f2);
// TODO(b/72858955): due to the potential reflective access, they should have different names
// by R8's improved reflective access detection or via keep rules.
- assertEquals(overloadaggressively, f1.field.name == f2.field.name);
+ assertEquals(overloadaggressively, f1.getReference().name == f2.getReference().name);
DexEncodedField f3 = a.field(B.class.getCanonicalName(), "f3").getField();
assertNotNull(f3);
// TODO(b/72858955): ditto
- assertEquals(overloadaggressively, f1.field.name == f3.field.name);
+ assertEquals(overloadaggressively, f1.getReference().name == f3.getReference().name);
// TODO(b/72858955): ditto
- assertEquals(overloadaggressively, f2.field.name == f3.field.name);
+ assertEquals(overloadaggressively, f2.getReference().name == f3.getReference().name);
String main = FieldUpdater.class.getCanonicalName();
ProcessResult javaOutput = runOnJavaRaw(main, classes);
@@ -143,7 +143,7 @@
assertNotNull(f3);
// TODO(b/72858955): due to the potential reflective access, they should have different names
// by R8's improved reflective access detection or via keep rules.
- assertEquals(overloadaggressively, f1.field.name == f3.field.name);
+ assertEquals(overloadaggressively, f1.getReference().name == f3.getReference().name);
String main = FieldResolution.class.getCanonicalName();
ProcessResult javaOutput = runOnJavaRaw(main, classes);
@@ -188,14 +188,14 @@
DexEncodedMethod m2 =
b.method("java.lang.Object", "getF2", ImmutableList.of()).getMethod();
// TODO(b/72858955): due to the potential reflective access, they should have different names.
- assertEquals(overloadaggressively, m1.method.name == m2.method.name);
+ assertEquals(overloadaggressively, m1.getReference().name == m2.getReference().name);
DexEncodedMethod m3 =
b.method("java.lang.String", "getF3", ImmutableList.of()).getMethod();
assertNotNull(m3);
// TODO(b/72858955): ditto
- assertEquals(overloadaggressively, m1.method.name == m3.method.name);
+ assertEquals(overloadaggressively, m1.getReference().name == m3.getReference().name);
// TODO(b/72858955): ditto
- assertEquals(overloadaggressively, m2.method.name == m3.method.name);
+ assertEquals(overloadaggressively, m2.getReference().name == m3.getReference().name);
String main = MethodResolution.class.getCanonicalName();
ProcessResult javaOutput = runOnJavaRaw(main, classes);
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java b/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
index 668206c..34d84c4 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.retrace.Retrace;
import com.android.tools.r8.retrace.RetraceCommand;
import com.android.tools.r8.utils.StringUtils;
@@ -17,6 +18,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -54,6 +56,10 @@
return addWithoutFileNameAndLineNumber(clazz.getTypeName(), methodName);
}
+ public Builder addWithoutFileNameAndLineNumber(ClassReference clazz, String methodName) {
+ return addWithoutFileNameAndLineNumber(clazz.getTypeName(), methodName);
+ }
+
public Builder addWithoutFileNameAndLineNumber(String className, String methodName) {
stackTraceLines.add(
StackTraceLine.builder().setClassName(className).setMethodName(methodName).build());
@@ -65,12 +71,19 @@
return this;
}
+ public Builder applyIf(boolean condition, Consumer<Builder> fn) {
+ if (condition) {
+ fn.accept(this);
+ }
+ return this;
+ }
+
public StackTrace build() {
return new StackTrace(
stackTraceLines,
StringUtils.join(
- stackTraceLines.stream().map(StackTraceLine::toString).collect(Collectors.toList()),
- "\n"));
+ "\n",
+ stackTraceLines.stream().map(StackTraceLine::toString).collect(Collectors.toList())));
}
}
diff --git a/src/test/java/com/android/tools/r8/regress/Regress181837660.java b/src/test/java/com/android/tools/r8/regress/Regress181837660.java
index 7fd9e77..b5e0a7c 100644
--- a/src/test/java/com/android/tools/r8/regress/Regress181837660.java
+++ b/src/test/java/com/android/tools/r8/regress/Regress181837660.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.regress;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -14,7 +16,6 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.dexsplitter.SplitterTestBase;
-import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,8 +29,6 @@
@RunWith(Parameterized.class)
public class Regress181837660 extends SplitterTestBase {
- public static final String EXPECTED = StringUtils.lines("42");
-
@Parameters(name = "{0}")
public static TestParametersCollection params() {
return getTestParameters().withDexRuntimes().withAllApiLevels().build();
@@ -67,10 +66,26 @@
FeatureClass.class,
b -> {},
this::configureNoInlineAnnotations);
- // TODO(b/181571571): This should not succeed as illustrated by non inlining case
- assertEquals(0, processResult.exitCode);
+ // This should not succeed as illustrated by non inlining case
+ assertEquals(1, processResult.exitCode);
// We can't actually read the field since it is in the feature.
- assertFalse(processResult.stderr.contains("NoClassDefFoundError"));
+ assertThat(processResult.stderr, containsString("NoClassDefFoundError"));
+ }
+
+ @Test
+ public void testRegress181571571StillInlineValid() throws Exception {
+ ProcessResult processResult =
+ testR8Splitter(
+ parameters,
+ ImmutableSet.of(Base2Class.class),
+ ImmutableSet.of(Feature2Class.class),
+ Feature2Class.class,
+ r8TestCompileResult ->
+ r8TestCompileResult.inspect(
+ base -> assertFalse(base.clazz(Base2Class.class).isPresent())),
+ this::configureNoInlineAnnotations);
+ assertEquals(0, processResult.exitCode);
+ assertEquals(processResult.stdout, "42\n");
}
private void configure(R8FullTestBuilder testBuilder) throws NoSuchMethodException {
@@ -83,20 +98,52 @@
}
public static class BaseClass {
+
@NeverInline
public static String getFromFeature() {
return FeatureClass.featureString;
}
+
+ @NeverInline
+ public static String getSecondFromFeature() {
+ return FeatureClass.getFeatureString();
+ }
}
public static class FeatureClass implements RunInterface {
public static String featureString = "22";
+ public static String getFeatureString() {
+ return "42";
+ }
+
public static String getAString() {
return BaseClass.getFromFeature();
}
+ public static String getSecondString() {
+ return BaseClass.getSecondFromFeature();
+ }
+
+ @Override
+ public void run() {
+ System.out.println(getAString());
+ System.out.println(getSecondString());
+ }
+ }
+
+ public static class Base2Class {
+ public static String getFromFeature() {
+ return System.currentTimeMillis() > 2 ? "42" : "-19";
+ }
+ }
+
+ public static class Feature2Class implements RunInterface {
+ public static String getAString() {
+ return Base2Class.getFromFeature();
+ }
+
@Override
public void run() {
System.out.println(getAString());
diff --git a/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java b/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java
index 0556439..33bef6d 100644
--- a/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java
+++ b/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java
@@ -232,7 +232,7 @@
return Arrays.stream(method.getMethod().getCode().asDexCode().instructions)
.filter(instruction -> instruction instanceof IgetObject)
.map(instruction -> (IgetObject) instruction)
- .filter(get -> get.getField() == field.getField().field)
+ .filter(get -> get.getField() == field.getField().getReference())
.count();
}
@@ -268,23 +268,33 @@
MethodSubject msvOnB = classB.method("void", "msv", ImmutableList.of());
assertThat(msvOnB, isPresent());
// Field load of volatile fields are never eliminated.
- assertEquals(5, countIget(mvOnA.getMethod().getCode().asDexCode(), vOnA.getField().field));
- assertEquals(5, countSget(msvOnA.getMethod().getCode().asDexCode(), svOnA.getField().field));
- assertEquals(5, countIget(mvOnB.getMethod().getCode().asDexCode(), vOnA.getField().field));
- assertEquals(5, countSget(msvOnB.getMethod().getCode().asDexCode(), svOnA.getField().field));
+ assertEquals(
+ 5, countIget(mvOnA.getMethod().getCode().asDexCode(), vOnA.getField().getReference()));
+ assertEquals(
+ 5, countSget(msvOnA.getMethod().getCode().asDexCode(), svOnA.getField().getReference()));
+ assertEquals(
+ 5, countIget(mvOnB.getMethod().getCode().asDexCode(), vOnA.getField().getReference()));
+ assertEquals(
+ 5, countSget(msvOnB.getMethod().getCode().asDexCode(), svOnA.getField().getReference()));
// For fields on the same class both separate compilation (D8) and whole program
// compilation (R8) will eliminate field loads on non-volatile fields.
- assertEquals(1, countIget(mfOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));
- assertEquals(1, countSget(msfOnA.getMethod().getCode().asDexCode(), sfOnA.getField().field));
assertEquals(
- 2, countIget(mfWithMonitorOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));
+ 1, countIget(mfOnA.getMethod().getCode().asDexCode(), fOnA.getField().getReference()));
+ assertEquals(
+ 1, countSget(msfOnA.getMethod().getCode().asDexCode(), sfOnA.getField().getReference()));
+ assertEquals(
+ 2,
+ countIget(
+ mfWithMonitorOnA.getMethod().getCode().asDexCode(), fOnA.getField().getReference()));
// For fields on other class both separate compilation (D8) and whole program
// compilation (R8) will differ in the eliminated field loads of non-volatile fields.
- assertEquals(mfOnBGets,
- countIget(mfOnB.getMethod().getCode().asDexCode(), fOnA.getField().field));
- assertEquals(msfOnBGets,
- countSget(msfOnB.getMethod().getCode().asDexCode(), sfOnA.getField().field));
+ assertEquals(
+ mfOnBGets,
+ countIget(mfOnB.getMethod().getCode().asDexCode(), fOnA.getField().getReference()));
+ assertEquals(
+ msfOnBGets,
+ countSget(msfOnB.getMethod().getCode().asDexCode(), sfOnA.getField().getReference()));
}
@Test
@@ -320,12 +330,17 @@
for (FieldSubject field : new FieldSubject[]{years, months, days}) {
- assertEquals(1,
- countIget(totalDays.getMethod().getCode().asDexCode(), field.getField().field));
- assertEquals(2,
- countIget(totalDaysTimes2.getMethod().getCode().asDexCode(), field.getField().field));
- assertEquals(3,
- countIget(totalDaysTimes3.getMethod().getCode().asDexCode(), field.getField().field));
+ assertEquals(
+ 1,
+ countIget(totalDays.getMethod().getCode().asDexCode(), field.getField().getReference()));
+ assertEquals(
+ 2,
+ countIget(
+ totalDaysTimes2.getMethod().getCode().asDexCode(), field.getField().getReference()));
+ assertEquals(
+ 3,
+ countIget(
+ totalDaysTimes3.getMethod().getCode().asDexCode(), field.getField().getReference()));
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java b/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
index 9a1ad72..788bb0a 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
@@ -125,7 +125,7 @@
if (isFlattenPackageHierarchy()) {
expectedPackageNames.add(packageName != null ? packageName : "a");
}
- return StringUtils.join(expectedPackageNames, ".");
+ return StringUtils.join(".", expectedPackageNames);
}
};
}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithDexItemBasedConstStringTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithDexItemBasedConstStringTest.java
index e374f2a..624bdfe 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithDexItemBasedConstStringTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithDexItemBasedConstStringTest.java
@@ -46,7 +46,7 @@
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
- .addMainDexClassRules(TestClass.class)
+ .addMainDexKeepClassRules(TestClass.class)
.apply(this::configureRepackaging)
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithMainDexListTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithMainDexListTest.java
index 4fc28f5..81183f5 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithMainDexListTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithMainDexListTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.repackage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.shaking.ProguardConfigurationParser.FLATTEN_PACKAGE_HIERARCHY;
import static com.android.tools.r8.shaking.ProguardConfigurationParser.REPACKAGE_CLASSES;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
@@ -13,6 +14,7 @@
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
@@ -22,6 +24,7 @@
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+// TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
@RunWith(Parameterized.class)
public class RepackageWithMainDexListTest extends RepackageTestBase {
@@ -54,7 +57,13 @@
// Debug mode to enable minimal main dex.
.debug()
.setMinApi(parameters.getApiLevel())
- .compile()
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyWarnings()
+ .assertWarningsMatch(
+ diagnosticType(UnsupportedMainDexListUsageDiagnostic.class)))
.apply(this::checkCompileResult)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutputLines("Hello world!");
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java
index 75d4bbc..4d4419f 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java
@@ -4,17 +4,17 @@
package com.android.tools.r8.resolution;
import static com.android.tools.r8.ToolHelper.getMostRecentAndroidJar;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.graph.ResolutionResult.IllegalAccessOrNoSuchMethodResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
@@ -30,17 +30,24 @@
public class VirtualOverrideOfPrivateStaticMethodTest extends TestBase {
public interface I {
- default void f() {}
+ default void f() {
+ System.out.println("I::f");
+ }
}
public static class A {
- private static void f() {}
+ private static void f() {
+ System.out.println("A::f");
+ }
}
public static class B extends A implements I {}
public static class C extends B {
- public void f() {}
+ @Override
+ public void f() {
+ System.out.println("C::f");
+ }
}
public static class Main {
@@ -64,13 +71,13 @@
.appInfo();
}
- private static DexMethod buildMethod(Class clazz, String name) {
+ private static DexMethod buildMethod(Class<?> clazz, String name) {
return buildNullaryVoidMethod(clazz, name, appInfo.dexItemFactory());
}
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
}
private final TestParameters parameters;
@@ -85,30 +92,48 @@
@Test
public void resolveTarget() {
ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
- assertTrue(resolutionResult instanceof IllegalAccessOrNoSuchMethodResult);
+ DexClass context = appInfo.definitionFor(methodOnB.holder);
+ assertTrue(resolutionResult.isIllegalAccessErrorResult(context, appInfo));
}
@Test
- public void runTest() throws ExecutionException, CompilationFailedException, IOException {
- if (parameters.isCfRuntime()) {
- testForJvm()
- .addProgramClasses(CLASSES)
- .run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatMatches(containsString(expectedRuntimeError()));
- }
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addProgramClasses(CLASSES)
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ }
+
+ @Test
+ public void testD8() throws ExecutionException, CompilationFailedException, IOException {
+ testForD8(parameters.getBackend())
+ .addProgramClasses(CLASSES)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ // TODO(b/182335909): Ideally, this should IllegalAccessError.
+ .applyIf(
+ parameters.canUseDefaultAndStaticInterfaceMethodsWhenDesugaring()
+ && parameters.isCfRuntime(),
+ r -> r.assertFailureWithErrorThatThrows(IllegalAccessError.class),
+ r -> r.assertSuccessWithOutputLines("C::f"));
+ }
+
+ @Test
+ public void testR8() throws ExecutionException, CompilationFailedException, IOException {
testForR8(parameters.getBackend())
.addProgramClasses(CLASSES)
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatMatches(containsString(expectedRuntimeError()));
+ .assertFailureWithErrorThatThrows(expectedRuntimeError());
}
- private String expectedRuntimeError() {
+ private Class<? extends Throwable> expectedRuntimeError() {
if (parameters.isDexRuntime()
&& parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
- return "IncompatibleClassChangeError";
+ return IncompatibleClassChangeError.class;
}
- return "IllegalAccessError";
+ return IllegalAccessError.class;
}
}
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
index c92f813..edc4c42 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
@@ -132,7 +132,7 @@
ResolutionResult resolutionResult =
appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
- assertEquals(methodOnBReference, resolved.method);
+ assertEquals(methodOnBReference, resolved.getReference());
assertFalse(resolutionResult.isVirtualTarget());
DexEncodedMethod singleVirtualTarget =
appInfo.lookupSingleVirtualTarget(methodOnBReference, methodOnB, false);
@@ -144,7 +144,7 @@
ResolutionResult resolutionResult =
appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
- assertEquals(methodOnBReference, resolved.method);
+ assertEquals(methodOnBReference, resolved.getReference());
assertFalse(resolutionResult.isVirtualTarget());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
index 2ffd43d..7843995 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
@@ -176,7 +176,7 @@
DexProgramClass bClass = appInfo.definitionForProgramType(methodOnB.holder);
ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
- assertEquals(methodOnA, resolved.method);
+ assertEquals(methodOnA, resolved.getReference());
assertFalse(resolutionResult.isVirtualTarget());
DexEncodedMethod singleVirtualTarget =
appInfo.lookupSingleVirtualTarget(methodOnB, bClass.getProgramDefaultInitializer(), false);
@@ -187,7 +187,7 @@
public void lookupVirtualTargets() {
ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
- assertEquals(methodOnA, resolved.method);
+ assertEquals(methodOnA, resolved.getReference());
assertFalse(resolutionResult.isVirtualTarget());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
index ce6f4d7..5498d06 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.graph.ResolutionResult.IllegalAccessOrNoSuchMethodResult;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.transformers.ClassFileTransformer;
import com.android.tools.r8.utils.BooleanUtils;
@@ -124,7 +123,11 @@
// Resolution fails when there is a mismatch between the symbolic reference and the definition.
if (!symbolicReferenceIsDefiningType) {
- assertTrue(resolutionResult instanceof IllegalAccessOrNoSuchMethodResult);
+ if (inSameNest) {
+ assertTrue(resolutionResult.isNoSuchMethodErrorResult(callerClassDefinition, appInfo));
+ } else {
+ assertTrue(resolutionResult.isIllegalAccessErrorResult(callerClassDefinition, appInfo));
+ }
return;
}
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
index c636ef9..e116329 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
@@ -67,7 +67,7 @@
appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, latticeB);
assertNotNull(singleTarget);
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
- assertEquals(fooB, singleTarget.method);
+ assertEquals(fooB, singleTarget.getReference());
}
@Test
@@ -94,7 +94,7 @@
appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, latticeB);
assertNotNull(singleTarget);
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
- assertEquals(fooB, singleTarget.method);
+ assertEquals(fooB, singleTarget.getReference());
}
@Test
@@ -133,7 +133,7 @@
lookupResult
.asLookupResultSuccess()
.forEach(
- clazzAndMethod -> actual.add(clazzAndMethod.getDefinition().method),
+ clazzAndMethod -> actual.add(clazzAndMethod.getDefinition().getReference()),
lambdaTarget -> {
assert false;
});
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
index a4b183c..85bd2ca 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
@@ -55,7 +55,7 @@
DexEncodedMethod singleTarget =
appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, null);
assertNotNull(singleTarget);
- assertEquals(fooA, singleTarget.method);
+ assertEquals(fooA, singleTarget.getReference());
DexEncodedMethod invalidSingleTarget =
appInfo.lookupSingleVirtualTarget(fooA, mainMethod, true, t -> false, typeA, null);
assertNull(invalidSingleTarget);
@@ -82,7 +82,7 @@
DexEncodedMethod singleTarget =
appInfo.lookupSingleVirtualTarget(fooI, mainMethod, true, t -> false, typeA, null);
assertNotNull(singleTarget);
- assertEquals(fooA, singleTarget.method);
+ assertEquals(fooA, singleTarget.getReference());
DexEncodedMethod invalidSingleTarget =
appInfo.lookupSingleVirtualTarget(fooI, mainMethod, false, t -> false, typeA, null);
assertNull(invalidSingleTarget);
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java b/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java
new file mode 100644
index 0000000..aa543c8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java
@@ -0,0 +1,161 @@
+// 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.retrace;
+
+import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileNameAndLineNumber;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.retrace.StackTrace;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+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 RetraceLambdaTest extends TestBase {
+
+ private static final String JAVAC_LAMBDA_METHOD = "lambda$main$0";
+
+ // TODO(b/172014416): These should not be needed once fixed.
+ private static final String LAMBDA_BRIDGE_METHOD = "$r8$lambda$dX5OYTAgq4ijGUv_zaGoVsFINMs";
+ private static final String INTERNAL_LAMBDA_CLASS =
+ Main.class.getTypeName()
+ + "$$InternalSyntheticLambda$0$11a5d582ed94e937718cf3ed497d4d164b60dfa85d606466457007fade57dce8$0";
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection parameters() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ private final TestParameters parameters;
+
+ public RetraceLambdaTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ testForRuntime(parameters)
+ .addInnerClasses(getClass())
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatMatches(containsString("Hello World!"))
+ .inspectStackTrace(
+ stackTrace -> {
+ assertThat(
+ stackTrace,
+ isSameExceptForFileNameAndLineNumber(
+ StackTrace.builder()
+ .addWithoutFileNameAndLineNumber(Main.class, JAVAC_LAMBDA_METHOD)
+ // TODO(b/172014416): Support a D8 mapping and prune the synthetic.
+ .applyIf(
+ parameters.isDexRuntime(),
+ b ->
+ b.addWithoutFileNameAndLineNumber(
+ SyntheticItemsTestUtils.syntheticLambdaClass(Main.class, 0),
+ "run"))
+ .addWithoutFileNameAndLineNumber(Main.class, "runIt")
+ .addWithoutFileNameAndLineNumber(Main.class, "main")
+ .build()));
+ });
+ }
+
+ @Test
+ public void testEverythingInlined() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepAttributeSourceFile()
+ .addKeepAttributeLineNumberTable()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatMatches(containsString("Hello World!"))
+ .inspectStackTrace(
+ stackTrace -> {
+ int frames = parameters.isCfRuntime() ? 2 : 1;
+ checkRawStackTraceFrameCount(stackTrace, frames, "Expected everything to be inlined");
+ checkCurrentlyIncorrectStackTrace(stackTrace, JAVAC_LAMBDA_METHOD);
+ });
+ }
+
+ @Test
+ public void testNothingInlined() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepPackageNamesRule(getClass().getPackage())
+ .noTreeShaking()
+ .addKeepAttributeSourceFile()
+ .addKeepAttributeLineNumberTable()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatMatches(containsString("Hello World!"))
+ .inspectStackTrace(
+ stackTrace -> {
+ int frames = parameters.isCfRuntime() ? 3 : 5;
+ checkRawStackTraceFrameCount(stackTrace, frames, "Expected nothing to be inlined");
+ checkCurrentlyIncorrectStackTrace(stackTrace, "lambda$main$0");
+ });
+ }
+
+ private void checkRawStackTraceFrameCount(
+ StackTrace stackTrace, int expectedFrames, String message) {
+ int linesFromTest = 0;
+ for (String line : stackTrace.getOriginalStderr().split("\n")) {
+ if (line.trim().startsWith("at " + getClass().getPackage().getName())) {
+ linesFromTest++;
+ }
+ }
+ assertEquals(message + stackTrace.getOriginalStderr(), expectedFrames, linesFromTest);
+ }
+
+ private void checkCurrentlyIncorrectStackTrace(StackTrace stackTrace, String javacLambdaMethod) {
+ assertThat(
+ stackTrace,
+ isSameExceptForFileNameAndLineNumber(
+ StackTrace.builder()
+ .addWithoutFileNameAndLineNumber(Main.class, javacLambdaMethod)
+ .applyIf(
+ parameters.isDexRuntime(),
+ b ->
+ b
+ // TODO(b/172014416): Lambda bridges should be marked synthetic
+ // and removed.
+ .addWithoutFileNameAndLineNumber(Main.class, LAMBDA_BRIDGE_METHOD)
+ // TODO(b/172014416): The frame mapping should have removed this
+ // entry.
+ // TODO(b/172014416): Synthetics should not map back to internal
+ // names.
+ .addWithoutFileNameAndLineNumber(INTERNAL_LAMBDA_CLASS, "run"))
+ .addWithoutFileNameAndLineNumber(Main.class, "runIt")
+ .addWithoutFileNameAndLineNumber(Main.class, "main")
+ .build()));
+ }
+
+ public interface MyRunner {
+ void run();
+ }
+
+ public static class Main {
+
+ public static void runIt(MyRunner runner) {
+ runner.run();
+ }
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ runIt(
+ () -> {
+ throw new RuntimeException("Hello World!");
+ });
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java b/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
new file mode 100644
index 0000000..8cdd48e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
@@ -0,0 +1,103 @@
+// 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.shaking;
+
+import com.android.tools.r8.NeverClassInline;
+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.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AbstractSuperClassLiveMethodTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final String NEW_DESCRIPTOR = "Lfoo/A;";
+ private final String[] EXPECTED = new String[] {"A::foo", "Base::foo"};
+ private final String[] EXPECTED_DALVIK = new String[] {"A::foo", "A::foo"};
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public AbstractSuperClassLiveMethodTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ public List<byte[]> getProgramClassFileData() throws Exception {
+ return ImmutableList.of(
+ transformer(A.class).setClassDescriptor(NEW_DESCRIPTOR).transform(),
+ transformer(Main.class)
+ .replaceClassDescriptorInMethodInstructions(descriptor(A.class), NEW_DESCRIPTOR)
+ .transform());
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
+ .addProgramClasses(Base.class)
+ .addProgramClassFileData(getProgramClassFileData())
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik(),
+ r -> r.assertSuccessWithOutputLines(EXPECTED_DALVIK),
+ r -> r.assertSuccessWithOutputLines(EXPECTED));
+ }
+
+ @Test
+ public void testForR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Base.class)
+ .addProgramClassFileData(getProgramClassFileData())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .addOptionsModification(options -> options.enableDevirtualization = false)
+ .run(parameters.getRuntime(), Main.class)
+ .applyIf(
+ parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik(),
+ r -> r.assertSuccessWithOutputLines(EXPECTED_DALVIK),
+ // TODO(b/182444403): Should succeed with EXPECTED.
+ r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class));
+ }
+
+ @NoVerticalClassMerging
+ public abstract static class Base {
+
+ @NeverInline
+ void foo() {
+ System.out.println("Base::foo");
+ }
+ }
+
+ @NeverClassInline
+ public static class /* will be foo.A */ A extends Base {
+
+ @Override
+ @NeverInline
+ public void foo() {
+ System.out.println("A::foo");
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ Base a = new A();
+ ((A) a).foo();
+ a.foo();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java b/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
index ddaf47f..aa2df28 100644
--- a/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
@@ -99,9 +99,9 @@
DexClass clazz = classSubject.getDexProgramClass();
assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) {
- assertTrue(encodedMethod.method.name.toString().startsWith("foo"));
+ assertTrue(encodedMethod.getReference().name.toString().startsWith("foo"));
MethodSubject methodSubject =
- classSubject.method(MethodSignature.fromDexMethod(encodedMethod.method));
+ classSubject.method(MethodSignature.fromDexMethod(encodedMethod.getReference()));
assertThat(methodSubject, isPresentAndNotRenamed());
}
}
@@ -135,9 +135,9 @@
DexClass clazz = classSubject.getDexProgramClass();
assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) {
- assertTrue(encodedMethod.method.name.toString().startsWith("foo"));
+ assertTrue(encodedMethod.getReference().name.toString().startsWith("foo"));
MethodSubject methodSubject =
- classSubject.method(MethodSignature.fromDexMethod(encodedMethod.method));
+ classSubject.method(MethodSignature.fromDexMethod(encodedMethod.getReference()));
assertThat(methodSubject, isPresentAndNotRenamed());
}
}
@@ -155,9 +155,9 @@
DexClass clazz = classSubject.getDexProgramClass();
assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) {
- assertTrue(encodedMethod.method.name.toString().startsWith("foo"));
+ assertTrue(encodedMethod.getReference().name.toString().startsWith("foo"));
MethodSubject methodSubject =
- classSubject.method(MethodSignature.fromDexMethod(encodedMethod.method));
+ classSubject.method(MethodSignature.fromDexMethod(encodedMethod.getReference()));
assertThat(methodSubject, isPresentAndNotRenamed());
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
index 3f27bc6..c3e53cf 100644
--- a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
@@ -254,7 +254,9 @@
.filter(InstructionSubject::isStaticGet)
.anyMatch(
instruction ->
- instruction.getField().equals(clinitFieldSubject.getField().field)));
+ instruction
+ .getField()
+ .equals(clinitFieldSubject.getField().getReference())));
});
}
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java
index 437cdd2..42268b2 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java
@@ -58,7 +58,7 @@
AppInfoWithLiveness appInfo, DexType type) {
DexProgramClass clazz = appInfo.definitionFor(type).asProgramClass();
DexEncodedMethod method =
- clazz.lookupVirtualMethod(m -> m.method.name.toString().equals("isEmpty"));
+ clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("isEmpty"));
assertTrue(method.isLibraryMethodOverride().isTrue());
}
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
index 331eb12..563a312 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
@@ -61,7 +61,7 @@
AppInfoWithLiveness appInfo, DexType type) {
DexProgramClass clazz = appInfo.definitionFor(type).asProgramClass();
DexEncodedMethod method =
- clazz.lookupVirtualMethod(m -> m.method.name.toString().equals("iterator"));
+ clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("iterator"));
// TODO(b/149976493): Mark library overrides from lambda instances.
if (parameters.isCfRuntime()) {
assertTrue(method.isLibraryMethodOverride().isFalse());
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
index f98e5ea..4a8306a 100644
--- a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
@@ -144,7 +144,7 @@
return false;
}
Version version = parameters.getRuntime().asDex().getVm().getVersion();
- return version.isOlderThanOrEqual(Version.V7_0_0) && version.isAtLeast(Version.V5_1_1);
+ return version.isOlderThanOrEqual(Version.V7_0_0) && version.isNewerThanOrEqual(Version.V5_1_1);
}
public static R8TestCompileResult compile(Dimensions dimensions) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/InnerClassesSimpleTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/InnerClassesSimpleTest.java
new file mode 100644
index 0000000..0474186
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/InnerClassesSimpleTest.java
@@ -0,0 +1,76 @@
+// 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.shaking.attributes;
+
+import static org.hamcrest.CoreMatchers.containsString;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.nio.file.Path;
+import java.util.List;
+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 InnerClassesSimpleTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final boolean minify;
+
+ @Parameters(name = "{0}, minify: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withCfRuntimes().build(), BooleanUtils.values());
+ }
+
+ public InnerClassesSimpleTest(TestParameters parameters, boolean minify) {
+ this.parameters = parameters;
+ this.minify = minify;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ Path path =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepPackageNamesRule(getClass().getPackage())
+ .noTreeShaking()
+ .applyIf(!minify, TestShrinkerBuilder::noMinification)
+ .compile()
+ .writeToZip();
+ testForR8(parameters.getBackend())
+ .addProgramFiles(path)
+ .addKeepAllClassesRule()
+ .allowDiagnosticInfoMessages(minify)
+ .compile()
+ // TODO(b/182524171): Prune inner class attributes if they are not kept.
+ .assertAllInfoMessagesMatch(containsString("Malformed inner-class attribute"))
+ .assertInfosCount(minify ? 4 : 0)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Hello World");
+ }
+
+ public interface MyRunner {
+ void run();
+ }
+
+ public static class Main {
+
+ public static void runIt(MyRunner runner) {
+ runner.run();
+ }
+
+ public static void main(String[] args) {
+ runIt(
+ () -> {
+ System.out.println("Hello World");
+ });
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
index 7111f51..34da969 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
@@ -74,13 +74,13 @@
}
private static void checkFieldInDictionary(FieldSubject field) {
- if (!names.contains(field.getField().field.name.toSourceString())) {
+ if (!names.contains(field.getField().getReference().name.toSourceString())) {
throw new AssertionError();
}
}
private static void checkMethodInDictionary(MethodSubject method) {
- String name = method.getMethod().method.name.toSourceString();
+ String name = method.getMethod().getReference().name.toSourceString();
if (!names.contains(name) && !name.equals("<init>") && !name.equals("main")) {
throw new AssertionError();
}
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java
index 311d6a6..e841ffc 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java
@@ -65,7 +65,8 @@
inspector.clazz(IfRuleWithApplyMappingTestClass.class).uniqueMethodWithName("method");
assertThat(methodSubject, isPresent());
assertEquals(
- A.class.getTypeName(), methodSubject.getMethod().method.proto.parameters.toSourceString());
+ A.class.getTypeName(),
+ methodSubject.getMethod().getReference().proto.parameters.toSourceString());
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java
index 230c0cf..221f99c 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java
@@ -100,7 +100,7 @@
@Test
public void testKeptMethod() throws Exception {
- assumeTrue(ToolHelper.getDexVm().getVersion().isAtLeast(Version.V7_0_0));
+ assumeTrue(ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(Version.V7_0_0));
MethodReference mainMethod =
methodFromMethod(Main.class.getDeclaredMethod("main", String[].class));
diff --git a/src/test/java/com/android/tools/r8/smali/ConstantFoldingTest.java b/src/test/java/com/android/tools/r8/smali/ConstantFoldingTest.java
index e5a8027..b9a9dc8 100644
--- a/src/test/java/com/android/tools/r8/smali/ConstantFoldingTest.java
+++ b/src/test/java/com/android/tools/r8/smali/ConstantFoldingTest.java
@@ -55,10 +55,12 @@
assertEquals(1, getNumberOfProgramClasses(processdApplication));
CodeInspector inspector = new CodeInspector(processdApplication);
ClassSubject clazz = inspector.clazz(DEFAULT_CLASS_NAME);
- clazz.forAllMethods(method -> {
- int index = Integer.parseInt(method.getMethod().method.name.toString().substring(1));
- checkers.get(index).accept(method.getMethod(), values.get(index));
- });
+ clazz.forAllMethods(
+ method -> {
+ int index =
+ Integer.parseInt(method.getMethod().getReference().name.toString().substring(1));
+ checkers.get(index).accept(method.getMethod(), values.get(index));
+ });
}
}
diff --git a/src/test/java/com/android/tools/r8/smali/OutlineTest.java b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
index a7b67bf..9324b87 100644
--- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java
+++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
@@ -870,7 +870,7 @@
List<DexType> r = new ArrayList<>();
for (DexEncodedMethod directMethod : outlineMethods) {
if (directMethod.getCode().asDexCode().instructions[0] instanceof InvokeVirtual) {
- r.add(directMethod.method.proto.returnType);
+ r.add(directMethod.getReference().proto.returnType);
}
}
assertEquals(2, r.size());
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliBuilder.java b/src/test/java/com/android/tools/r8/smali/SmaliBuilder.java
index e9368e9..0a2c7ab 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliBuilder.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliBuilder.java
@@ -42,8 +42,14 @@
@Override
public String toString() {
- return returnType + " " + clazz + "." + name
- + "(" + StringUtils.join(parameterTypes, ",") + ")";
+ return returnType
+ + " "
+ + clazz
+ + "."
+ + name
+ + "("
+ + StringUtils.join(",", parameterTypes)
+ + ")";
}
}
diff --git a/src/test/java/com/android/tools/r8/testing/StackTraceTest.java b/src/test/java/com/android/tools/r8/testing/StackTraceTest.java
index 33915ef..41b6de3 100644
--- a/src/test/java/com/android/tools/r8/testing/StackTraceTest.java
+++ b/src/test/java/com/android/tools/r8/testing/StackTraceTest.java
@@ -40,12 +40,12 @@
public void testJvmStackTrace() throws Exception {
String stderr =
StringUtils.join(
+ "\n",
ImmutableList.of(
"Exception in thread \"main\" java.lang.RuntimeException",
"\tat com.example.A.method2(Test.java:30)",
"\tat com.example.A.method1(Test.java:20)",
- "\tat com.example.Main.main(Test.java:10)"),
- "\n");
+ "\tat com.example.Main.main(Test.java:10)"));
checkStackTrace(StackTrace.extractFromJvm(stderr));
}
@@ -95,8 +95,7 @@
"\tat com.example.Main.main(Test.java:10)",
"dex2oat I 10-30 11:41:40 232588 232588 dex2oat.cc:2808] dex2oat took 94.860ms"
+ " (71.941ms cpu) (threads: 72) arena alloc=3KB (3312B) java alloc=32KB (32800B)"
- + " native alloc=440KB (450720B) free=9MB (9539424B)"
- );
+ + " native alloc=440KB (450720B) free=9MB (9539424B)");
checkStackTrace(StackTrace.extractFromArt(stderr, DexVm.ART_5_1_1_HOST));
}
diff --git a/src/test/java/com/android/tools/r8/utils/AppComparator.java b/src/test/java/com/android/tools/r8/utils/AppComparator.java
index 3436b9a..9dcec97 100644
--- a/src/test/java/com/android/tools/r8/utils/AppComparator.java
+++ b/src/test/java/com/android/tools/r8/utils/AppComparator.java
@@ -60,10 +60,11 @@
CodeInspector inspect2 = new CodeInspector(app2, Paths.get(MAP_2));
// Define your own tester to pick methods to inspect.
- Predicate<DexEncodedMethod> methodTester = encodedMethod -> {
- return encodedMethod.method.name.toString().equals("run")
- && encodedMethod.method.getArity() == 0;
- };
+ Predicate<DexEncodedMethod> methodTester =
+ encodedMethod -> {
+ return encodedMethod.getReference().name.toString().equals("run")
+ && encodedMethod.getReference().getArity() == 0;
+ };
inspect1.forAllClasses(clazz1 -> {
clazz1.forAllMethods(method1 -> {
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java
index 693af00..26e85e5 100644
--- a/src/test/java/com/android/tools/r8/utils/Smali.java
+++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -79,7 +79,7 @@
if (parser.getNumberOfSyntaxErrors() > 0 || lexer.getNumberOfSyntaxErrors() > 0) {
throw new RuntimeException(
- "Error occured while compiling text:\n" + StringUtils.join(smaliTexts, "\n"));
+ "Error occured while compiling text:\n" + StringUtils.join("\n", smaliTexts));
}
CommonTree t = result.getTree();
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java
index 7059ae1..2b57e91 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java
@@ -19,7 +19,7 @@
if (!targetSubject.isPresent()) {
throw new IllegalArgumentException();
}
- DexField target = targetSubject.getField().field;
+ DexField target = targetSubject.getField().getReference();
return new TypeSafeMatcher<MethodSubject>() {
@Override
protected boolean matchesSafely(MethodSubject subject) {
@@ -79,7 +79,7 @@
if (!targetSubject.isPresent()) {
throw new IllegalArgumentException();
}
- DexMethod target = targetSubject.getMethod().method;
+ DexMethod target = targetSubject.getMethod().getReference();
return new TypeSafeMatcher<MethodSubject>() {
@Override
protected boolean matchesSafely(MethodSubject subject) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
index ef44c64..aae1912 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
@@ -15,7 +15,7 @@
public abstract DexEncodedField getField();
public DexField getDexField() {
- return getField().field;
+ return getField().getReference();
}
public abstract DexValue getStaticValue();
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index ed04f35..be358de 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -121,7 +121,7 @@
private DexEncodedMethod findMethod(Iterable<DexEncodedMethod> methods, DexMethod dexMethod) {
for (DexEncodedMethod method : methods) {
- if (method.method.equals(dexMethod)) {
+ if (method.getReference().equals(dexMethod)) {
return method;
}
}
@@ -320,7 +320,7 @@
private DexEncodedField findField(List<DexEncodedField> fields, DexField dexField) {
for (DexEncodedField field : fields) {
- if (field.field.equals(dexField)) {
+ if (field.getReference().equals(dexField)) {
return field;
}
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
index b071916..023f412 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
@@ -43,7 +43,7 @@
}
public TypeSubject type() {
- return new TypeSubject(codeInspector, dexField.field.type);
+ return new TypeSubject(codeInspector, dexField.getReference().type);
}
@Override
@@ -79,7 +79,7 @@
@Override
public FieldSignature getFinalSignature() {
- return FieldSignature.fromDexField(dexField.field);
+ return FieldSignature.fromDexField(dexField.getReference());
}
@Override
@@ -123,7 +123,9 @@
@Override
public String getJvmFieldSignatureAsString() {
- return dexField.field.name.toString() + ":" + dexField.field.type.toDescriptorString();
+ return dexField.getReference().name.toString()
+ + ":"
+ + dexField.getReference().type.toDescriptorString();
}
@Override
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index dfccf5a..0eb0de1 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -155,7 +155,7 @@
@Override
public MethodSignature getFinalSignature() {
- return MethodSignature.fromDexMethod(dexMethod.method);
+ return MethodSignature.fromDexMethod(dexMethod.getReference());
}
@Override
@@ -273,7 +273,7 @@
}
Object2IntMap<InstructionSubject> lineNumberTable = new Object2IntOpenHashMap<>();
DexDebugPositionState state =
- new DexDebugPositionState(debugInfo.startLine, getMethod().method);
+ new DexDebugPositionState(debugInfo.startLine, getMethod().getReference());
Iterator<DexDebugEvent> iterator = Arrays.asList(debugInfo.events).iterator();
for (Instruction insn : code.instructions) {
int offset = insn.getOffset();
@@ -337,7 +337,7 @@
}
public MethodReference asMethodReference() {
- DexMethod method = dexMethod.method;
+ DexMethod method = dexMethod.getReference();
return Reference.method(
Reference.classFromDescriptor(method.holder.toDescriptorString()),
method.name.toString(),
@@ -349,13 +349,15 @@
@Override
public String getJvmMethodSignatureAsString() {
- return dexMethod.method.name.toString()
+ return dexMethod.getName().toString()
+ "("
+ StringUtils.join(
- Arrays.stream(dexMethod.method.proto.parameters.values)
- .map(DexType::toDescriptorString).collect(Collectors.toList()), "")
+ "",
+ Arrays.stream(dexMethod.getParameters().values)
+ .map(DexType::toDescriptorString)
+ .collect(Collectors.toList()))
+ ")"
- + dexMethod.method.proto.returnType.toDescriptorString();
+ + dexMethod.returnType().toDescriptorString();
}
@Override
diff --git a/tools/archive_desugar_jdk_libs.py b/tools/archive_desugar_jdk_libs.py
index 403212f..825cb91 100755
--- a/tools/archive_desugar_jdk_libs.py
+++ b/tools/archive_desugar_jdk_libs.py
@@ -85,10 +85,12 @@
'https://github.com/'
+ github_account + '/' + LIBRARY_NAME, checkout_dir)
-def BuildDesugaredLibrary(checkout_dir):
+def BuildDesugaredLibrary(checkout_dir, variant):
+ if (variant != 'jdk8' and variant != 'jdk11'):
+ raise Exception('Variant ' + variant + 'is not supported')
with utils.ChangedWorkingDirectory(checkout_dir):
bazel = os.path.join(utils.BAZEL_TOOL, 'lib', 'bazel', 'bin', 'bazel')
- cmd = [bazel, 'build', 'maven_release']
+ cmd = [bazel, 'build', 'maven_release' + ('_jdk11' if variant == 'jdk11' else '')]
utils.PrintCmd(cmd)
subprocess.check_call(cmd)
cmd = [bazel, 'shutdown']
@@ -97,9 +99,16 @@
# Locate the library jar and the maven zip with the jar from the
# bazel build.
- library_jar = os.path.join(
- checkout_dir, 'bazel-bin', 'src', 'share', 'classes', 'java', 'libjava.jar')
- maven_zip = os.path.join(checkout_dir, 'bazel-bin', LIBRARY_NAME +'.zip')
+ if variant == 'jdk8':
+ library_jar = os.path.join(
+ checkout_dir, 'bazel-bin', 'src', 'share', 'classes', 'java', 'libjava.jar')
+ else:
+ library_jar = os.path.join(
+ checkout_dir, 'bazel-bin', 'jdk11', 'src', 'java_base_selected.jar')
+ maven_zip = os.path.join(
+ checkout_dir,
+ 'bazel-bin',
+ LIBRARY_NAME + ('_jdk11' if variant != 'jdk11' else '') +'.zip')
return (library_jar, maven_zip)
@@ -124,11 +133,12 @@
# Make sure bazel is extracted in third_party.
utils.DownloadFromGoogleCloudStorage(utils.BAZEL_SHA_FILE)
utils.DownloadFromGoogleCloudStorage(utils.JAVA8_SHA_FILE)
+ utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE)
if options.build_only:
with utils.TempDir() as checkout_dir:
CloneDesugaredLibrary(options.github_account, checkout_dir)
- (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir)
+ (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, "jdk8")
shutil.copyfile(
library_jar,
os.path.join(options.build_only, os.path.basename(library_jar)))
@@ -150,7 +160,7 @@
raise Exception(
'Target archive directory %s already exists' % destination)
- (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir)
+ (library_jar, maven_zip) = BuildDesugaredLibrary(checkout_dir, "jdk8")
storage_path = LIBRARY_NAME + '/' + version
# Upload the jar file with the library.
diff --git a/tools/test.py b/tools/test.py
index 9e2a3e2..f7b204f 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -162,6 +162,8 @@
help='Enable Java debug agent and suspend compilation (default disabled)',
default=False,
action='store_true')
+ result.add_option('--desugared-library-configuration', '--desugared_library-configuration',
+ help='Use alternative desugared library configuration.')
result.add_option('--desugared-library', '--desugared_library',
help='Build and use desugared library from GitHub.')
return result.parse_args()
@@ -181,6 +183,13 @@
if utils.is_bot():
gradle.RunGradle(['--no-daemon', 'clean'])
+ desugar_jdk_json_dir = None
+ if options.desugared_library_configuration:
+ if options.desugared_library_configuration != 'jdk11':
+ print("Only value supported for --desugared-library is 'jdk11'")
+ exit(1)
+ desugar_jdk_json_dir = 'src/library_desugar/jdk11'
+
desugar_jdk_libs = None
if options.desugared_library:
if options.desugared_library != 'HEAD':
@@ -195,12 +204,12 @@
# Make sure bazel is extracted in third_party.
utils.DownloadFromGoogleCloudStorage(utils.BAZEL_SHA_FILE)
utils.DownloadFromGoogleCloudStorage(utils.JAVA8_SHA_FILE)
- (library_jar, maven_zip) = archive_desugar_jdk_libs.BuildDesugaredLibrary(checkout_dir)
+ utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE)
+ (library_jar, maven_zip) = archive_desugar_jdk_libs.BuildDesugaredLibrary(checkout_dir, 'jdk11' if options.desugared_library_configuration == 'jdk11' else 'jdk8')
desugar_jdk_libs = os.path.join(desugar_jdk_libs_dir, os.path.basename(library_jar))
shutil.copyfile(library_jar, desugar_jdk_libs)
print('Desugared library for test in ' + desugar_jdk_libs)
-
gradle_args = ['--stacktrace']
if utils.is_bot():
# Bots don't like dangling processes.
@@ -284,6 +293,8 @@
gradle_args.append('--no-daemon')
if options.debug_agent:
gradle_args.append('--no-daemon')
+ if desugar_jdk_json_dir:
+ gradle_args.append('-Pdesugar_jdk_json_dir=' + desugar_jdk_json_dir)
if desugar_jdk_libs:
gradle_args.append('-Pdesugar_jdk_libs=' + desugar_jdk_libs)
diff --git a/tools/utils.py b/tools/utils.py
index 1820991..da4a0e4 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -83,6 +83,7 @@
BAZEL_SHA_FILE = os.path.join(THIRD_PARTY, 'bazel.tar.gz.sha1')
BAZEL_TOOL = os.path.join(THIRD_PARTY, 'bazel')
JAVA8_SHA_FILE = os.path.join(THIRD_PARTY, 'openjdk', 'jdk8', 'linux-x86.tar.gz.sha1')
+JAVA11_SHA_FILE = os.path.join(THIRD_PARTY, 'openjdk', 'jdk-11', 'linux.tar.gz.sha1')
IGNORE_WARNINGS_RULES = os.path.join(REPO_ROOT, 'src', 'test', 'ignorewarnings.rules')
ANDROID_HOME_ENVIROMENT_NAME = "ANDROID_HOME"