Merge commit '1d37738b84cf0c6ad30d3d746ae8426b5a506cc8' into dev-release
diff --git a/src/library_desugar/jdk11/chm_only_desugar_jdk_libs.json b/src/library_desugar/jdk11/chm_only_desugar_jdk_libs.json
index f3a4daa..565ffd9 100644
--- a/src/library_desugar/jdk11/chm_only_desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/chm_only_desugar_jdk_libs.json
@@ -3,7 +3,7 @@
"group_id" : "com.tools.android",
"artifact_id" : "chm_only_desugar_jdk_libs",
"version": "1.0.12",
- "required_compilation_api_level": 30,
+ "required_compilation_api_level": 31,
"synthesized_library_classes_package_prefix": "j$.",
"support_all_callbacks_from_library": false,
"common_flags": [
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index b075745..fb03dbb 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -3,7 +3,7 @@
"group_id" : "com.tools.android",
"artifact_id" : "desugar_jdk_libs",
"version": "2.0.0",
- "required_compilation_api_level": 30,
+ "required_compilation_api_level": 31,
"synthesized_library_classes_package_prefix": "j$.",
"support_all_callbacks_from_library": true,
"common_flags": [
@@ -205,7 +205,7 @@
"java.nio.charset.StandardCharsets": "j$.nio.charset.StandardCharsets"
},
"retarget_lib_member": {
- "java.lang.Character#isBmpCodePoint": "java.lang.DesugarCharacter"
+ "java.lang.Character#isBmpCodePoint": "j$.lang.DesugarCharacter"
}
}
],
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
index 1482909..fac2ec0 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
@@ -3,7 +3,7 @@
"group_id" : "com.tools.android",
"artifact_id" : "desugar_jdk_libs_alternative_3",
"version": "2.0.0",
- "required_compilation_api_level": 30,
+ "required_compilation_api_level": 31,
"synthesized_library_classes_package_prefix": "j$.",
"support_all_callbacks_from_library": false,
"common_flags": [
@@ -209,7 +209,7 @@
"java.nio.charset.StandardCharsets": "j$.nio.charset.StandardCharsets"
},
"retarget_lib_member": {
- "java.lang.Character#isBmpCodePoint": "java.lang.DesugarCharacter"
+ "java.lang.Character#isBmpCodePoint": "j$.lang.DesugarCharacter"
}
}
],
diff --git a/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java b/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
index 7ef1569..bce73f0 100644
--- a/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
+++ b/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
@@ -105,7 +105,7 @@
InternalOptions getInternalOptions() {
InternalOptions options = new InternalOptions(factory, getReporter());
options.setMinApiLevel(AndroidApiLevel.getAndroidApiLevel(minApiLevel));
- options.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
+ options.desugaredLibrarySpecification = desugaredLibrarySpecification;
return options;
}
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 0967f55..8dd34a8 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -498,7 +498,8 @@
internal.encodeChecksums = getIncludeClassesChecksum();
internal.dexClassChecksumFilter = getDexClassChecksumFilter();
internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
- internal.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
+
+ internal.desugaredLibrarySpecification = desugaredLibrarySpecification;
internal.synthesizedClassPrefix = synthesizedClassPrefix;
internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 6da92e2..26c99ce 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -194,7 +194,7 @@
internal.enableInheritanceClassInDexDistributor = false;
assert desugaredLibrarySpecification != null;
- internal.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
+ internal.desugaredLibrarySpecification = desugaredLibrarySpecification;
internal.synthesizedClassPrefix =
desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix();
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 85c05f6..194c531 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -311,7 +311,7 @@
if (!options.mainDexKeepRules.isEmpty()) {
MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
}
- if (options.machineDesugaredLibrarySpecification.hasRetargeting()) {
+ if (!options.desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty()) {
DesugaredLibraryRetargeterLibraryTypeSynthesizer.checkForAssumedLibraryTypes(appView);
DesugaredLibraryRetargeterLibraryTypeSynthesizer.amendLibraryWithRetargetedMembers(appView);
}
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 5bc9ddd..bf04680 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -943,7 +943,7 @@
internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
- internal.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
+ internal.desugaredLibrarySpecification = desugaredLibrarySpecification;
internal.synthesizedClassPrefix = synthesizedClassPrefix;
internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
index cce0852..2e2aa7a 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ConsumerUtils;
import com.google.common.collect.ImmutableList;
@@ -17,6 +18,7 @@
public class AndroidApiReferenceLevelCache {
+ private final LegacyDesugaredLibrarySpecification desugaredLibrarySpecification;
private final AndroidApiLevelCompute apiLevelCompute;
private final AndroidApiLevelDatabase androidApiLevelDatabase;
private final AppView<?> appView;
@@ -31,6 +33,7 @@
factory = appView.dexItemFactory();
androidApiLevelDatabase =
new AndroidApiLevelHashingDatabaseImpl(predefinedApiTypeLookupForHashing);
+ desugaredLibrarySpecification = appView.options().desugaredLibrarySpecification;
}
public static AndroidApiReferenceLevelCache create(
@@ -72,7 +75,7 @@
if (reference.getContextType() == factory.objectType) {
return appView.computedMinApiLevel();
}
- if (appView.options().machineDesugaredLibrarySpecification.isSupported(reference)) {
+ if (desugaredLibrarySpecification.isSupported(reference, appView)) {
// If we end up desugaring the reference, the library classes is bridged by j$ which is part
// of the program.
return appView.computedMinApiLevel();
diff --git a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
index ef86f73..f9b13a4 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -19,6 +19,7 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ThrowExceptionCode;
import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.CommittedItems;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
@@ -111,10 +112,12 @@
new ConcurrentHashMap<>();
private final Set<DexType> seenTypes = Sets.newConcurrentHashSet();
private final AndroidApiLevelCompute apiLevelCompute;
+ private final LegacyDesugaredLibrarySpecification desugaredLibraryConfiguration;
public ApiReferenceStubber(AppView<? extends AppInfoWithClassHierarchy> appView) {
this.appView = appView;
apiLevelCompute = appView.apiLevelCompute();
+ desugaredLibraryConfiguration = appView.options().desugaredLibrarySpecification;
}
public void run(ExecutorService executorService) throws ExecutionException {
@@ -217,10 +220,7 @@
|| libraryClass.getType().toDescriptorString().startsWith("Ljava/")) {
return;
}
- if (appView
- .options()
- .machineDesugaredLibrarySpecification
- .isSupported(libraryClass.getType())) {
+ if (desugaredLibraryConfiguration.isSupported(libraryClass.getType(), appView)) {
return;
}
appView
diff --git a/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java b/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java
index eaec5a0..a720021 100644
--- a/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java
+++ b/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java
@@ -13,7 +13,7 @@
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.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.references.ArrayReference;
import com.android.tools.r8.references.ClassReference;
@@ -32,11 +32,13 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.NopDiagnosticsHandler;
+import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.TypeReferenceUtils;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
@@ -69,7 +71,7 @@
return false;
}
return namingLens.hasPrefixRewritingLogic()
- || options.machineDesugaredLibrarySpecification.hasEmulatedInterfaces();
+ || options.desugaredLibrarySpecification.hasEmulatedLibraryInterfaces();
}
private void run() {
@@ -78,15 +80,18 @@
}
private Predicate<DexType> createTargetPredicate() {
- MachineDesugaredLibrarySpecification desugaredLibrarySpecification =
- options.machineDesugaredLibrarySpecification;
+ LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
+ options.desugaredLibrarySpecification;
+ Set<DexType> potentialTypesToKeep =
+ SetUtils.newIdentityHashSet(
+ desugaredLibrarySpecification.getCustomConversions().values(),
+ desugaredLibrarySpecification.getEmulateLibraryInterface().values());
byte[] synthesizedLibraryClassesPackageDescriptorPrefix =
DexString.encodeToMutf8(
"L" + desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix());
return type ->
namingLens.prefixRewrittenType(type) != null
- || desugaredLibrarySpecification.isEmulatedInterfaceRewrittenType(type)
- || desugaredLibrarySpecification.isCustomConversionRewrittenType(type)
+ || potentialTypesToKeep.contains(type)
|| type.getDescriptor().startsWith(synthesizedLibraryClassesPackageDescriptorPrefix);
}
diff --git a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
index 3e33ca8..cc05c31 100644
--- a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
+++ b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
@@ -25,7 +25,7 @@
static CodeToKeep createCodeToKeep(InternalOptions options, NamingLens namingLens) {
if ((!namingLens.hasPrefixRewritingLogic()
- && !options.machineDesugaredLibrarySpecification.hasEmulatedInterfaces())
+ && !options.desugaredLibrarySpecification.hasEmulatedLibraryInterfaces())
|| options.isDesugaredLibraryCompilation()
|| options.testing.enableExperimentalDesugaredLibraryKeepRuleGenerator) {
return new NopCodeToKeep();
@@ -57,23 +57,27 @@
}
private final NamingLens namingLens;
+ private final Set<DexType> potentialTypesToKeep = Sets.newIdentityHashSet();
private final Map<DexType, KeepStruct> toKeep = new ConcurrentHashMap<>();
private final InternalOptions options;
public DesugaredLibraryCodeToKeep(NamingLens namingLens, InternalOptions options) {
this.namingLens = namingLens;
this.options = options;
+ potentialTypesToKeep.addAll(
+ options.desugaredLibrarySpecification.getEmulateLibraryInterface().values());
+ potentialTypesToKeep.addAll(
+ options.desugaredLibrarySpecification.getCustomConversions().values());
}
private boolean shouldKeep(DexType type) {
return namingLens.prefixRewrittenType(type) != null
- || options.machineDesugaredLibrarySpecification.isCustomConversionRewrittenType(type)
- || options.machineDesugaredLibrarySpecification.isEmulatedInterfaceRewrittenType(type)
+ || potentialTypesToKeep.contains(type)
// TODO(b/158632510): This should prefix match on DexString.
|| type.toDescriptorString()
.startsWith(
"L"
- + options.machineDesugaredLibrarySpecification
+ + options.desugaredLibrarySpecification
.getSynthesizedLibraryClassesPackagePrefix());
}
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 11d7e80..f99e380 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
@@ -128,16 +128,24 @@
DexMethod original = appView.graphLens().getOriginalMethodSignature(method);
assert original != null;
MethodProvider provider = rewritableMethods.getProvider(original);
- // Old versions of desugared library have in the jar file pre-desugared code. This is used
- // to undesugar pre-desugared code, then the code is re-desugared with D8/R8. This is
- // maintained for legacy only, recent desugared library should not be shipped with
- // pre-desugared code.
- Map<DexType, DexType> legacyBackport =
- appView.options().machineDesugaredLibrarySpecification.getLegacyBackport();
+ // TODO(b/150693139): Since the DesugarLibraryRetargeter is run during IR processing while the
+ // backported method rewriter is run in cf to cf, we need here to compute if the method is
+ // actually going to be retargeted through desugared library backports, and compute the
+ // corresponding backported method if so. This can be removed once the DesugarLibraryRetargeter
+ // has been moved as a cf to cf transformation.
if (provider == null
&& appView.options().isDesugaredLibraryCompilation()
- && legacyBackport.containsKey(method.holder)) {
- DexType newHolder = legacyBackport.get(method.holder);
+ && appView
+ .options()
+ .desugaredLibrarySpecification
+ .getBackportCoreLibraryMember()
+ .containsKey(method.holder)) {
+ DexType newHolder =
+ appView
+ .options()
+ .desugaredLibrarySpecification
+ .getBackportCoreLibraryMember()
+ .get(method.holder);
DexMethod backportedMethod =
appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
provider = rewritableMethods.getProvider(backportedMethod);
@@ -1437,7 +1445,7 @@
}
private void addProvider(MethodProvider generator) {
- if (appView.options().machineDesugaredLibrarySpecification.isSupported(generator.method)) {
+ if (appView.options().desugaredLibrarySpecification.isSupported(generator.method, appView)) {
// TODO(b/174453232): Remove this after the configuration file format has bee updated
// with the "rewrite_method" section.
if (generator.method.getHolderType() == appView.dexItemFactory().objectsType) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
index 1243435..1fd0ad0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
@@ -57,7 +57,7 @@
InterfaceMethodProcessorFacade interfaceMethodProcessorFacade,
RetargetingInfo retargetingInfo) {
ArrayList<CfPostProcessingDesugaring> desugarings = new ArrayList<>();
- if (appView.options().machineDesugaredLibrarySpecification.hasRetargeting()
+ if (!appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty()
&& !appView.options().isDesugaredLibraryCompilation()) {
desugarings.add(new DesugaredLibraryRetargeterPostProcessor(appView, retargetingInfo));
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index e55c246..33c69ac 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -82,9 +82,9 @@
this.nestBasedAccessDesugaring = NestBasedAccessDesugaring.create(appView);
BackportedMethodRewriter backportedMethodRewriter = null;
desugaredLibraryRetargeter =
- appView.options().machineDesugaredLibrarySpecification.hasRetargeting()
- ? new DesugaredLibraryRetargeter(appView)
- : null;
+ appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty()
+ ? null
+ : new DesugaredLibraryRetargeter(appView);
if (desugaredLibraryRetargeter != null) {
desugarings.add(desugaredLibraryRetargeter);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
index 90f2505..bf96b67 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
@@ -4,11 +4,20 @@
package com.android.tools.r8.ir.desugar;
+import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexItemFactory;
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.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@@ -22,7 +31,7 @@
public abstract DexType rewrittenType(DexType type, AppView<?> appView);
- public abstract DexType rewrittenContextType(DexType type);
+ public abstract DexType rewrittenContextType(DexType type, AppView<?> appView);
public boolean hasRewrittenType(DexType type, AppView<?> appView) {
return rewrittenType(type, appView) != null;
@@ -44,34 +53,195 @@
public abstract void forAllRewrittenTypes(Consumer<DexType> consumer);
- public static class MachineDesugarPrefixRewritingMapper extends PrefixRewritingMapper {
+ public static class DesugarPrefixRewritingMapper extends PrefixRewritingMapper {
- private final Map<DexType, DexType> rewriteType;
- private final Map<DexType, DexType> rewriteDerivedTypeOnly;
+ private final Set<DexType> notRewritten = Sets.newConcurrentHashSet();
+ private final Map<DexType, DexType> rewritten = new ConcurrentHashMap<>();
+ private final Map<DexString, DexString> initialPrefixes;
+ private final DexItemFactory factory;
+ private final boolean l8Compilation;
- public MachineDesugarPrefixRewritingMapper(MachineDesugaredLibrarySpecification specification) {
- this.rewriteType = new ConcurrentHashMap<>(specification.getRewriteType());
- rewriteDerivedTypeOnly = specification.getRewriteDerivedTypeOnly();
+ public DesugarPrefixRewritingMapper(
+ Map<String, String> prefixes, DexItemFactory itemFactory, boolean libraryCompilation) {
+ assert itemFactory != null || prefixes.isEmpty();
+ this.factory = itemFactory;
+ this.l8Compilation = libraryCompilation;
+ ImmutableMap.Builder<DexString, DexString> builder = ImmutableMap.builder();
+ for (String key : prefixes.keySet()) {
+ builder.put(toDescriptorPrefix(key), toDescriptorPrefix(prefixes.get(key)));
+ }
+ this.initialPrefixes = builder.build();
+ validatePrefixes(prefixes);
+ }
+
+ private DexString toDescriptorPrefix(String prefix) {
+ return factory.createString("L" + DescriptorUtils.getBinaryNameFromJavaType(prefix));
+ }
+
+ @Override
+ public void forAllRewrittenTypes(Consumer<DexType> consumer) {
+ rewritten.keySet().forEach(consumer);
+ }
+
+ private void validatePrefixes(Map<String, String> initialPrefixes) {
+ String[] prefixes = initialPrefixes.keySet().toArray(new String[0]);
+ for (int i = 0; i < prefixes.length; i++) {
+ for (int j = i + 1; j < prefixes.length; j++) {
+ String small, large;
+ if (prefixes[i].length() < prefixes[j].length()) {
+ small = prefixes[i];
+ large = prefixes[j];
+ } else {
+ small = prefixes[j];
+ large = prefixes[i];
+ }
+ if (large.startsWith(small)) {
+ throw new CompilationError(
+ "Inconsistent prefix in desugared library:"
+ + " Should a class starting with "
+ + small
+ + " be rewritten using "
+ + small
+ + " -> "
+ + initialPrefixes.get(small)
+ + " or using "
+ + large
+ + " - > "
+ + initialPrefixes.get(large)
+ + " ?");
+ }
+ }
+ }
}
@Override
public DexType rewrittenType(DexType type, AppView<?> appView) {
- if (type.isArrayType()) {
- DexType rewrittenBaseType =
- rewrittenType(type.toBaseType(appView.dexItemFactory()), appView);
- if (rewrittenBaseType == null) {
- return null;
- }
- return appView
- .dexItemFactory()
- .createArrayType(type.getNumberOfLeadingSquareBrackets(), rewrittenBaseType);
+ assert appView != null || l8Compilation;
+ if (notRewritten.contains(type)) {
+ return null;
}
+ if (rewritten.containsKey(type)) {
+ return rewritten.get(type);
+ }
+ return computePrefix(type, appView);
+ }
+
+ @Override
+ public DexType rewrittenContextType(DexType type, AppView<?> appView) {
+ DexType rewritten = rewrittenType(type, appView);
+ if (rewritten != null) {
+ return rewritten;
+ }
+ LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
+ appView.options().desugaredLibrarySpecification;
+ if (desugaredLibrarySpecification.getEmulateLibraryInterface().containsKey(type)) {
+ return desugaredLibrarySpecification.getEmulateLibraryInterface().get(type);
+ }
+ for (Map<DexType, DexType> value :
+ desugaredLibrarySpecification.getRetargetCoreLibMember().values()) {
+ if (value.containsKey(type)) {
+ // Hack until machine specification are ready.
+ String prefix =
+ DescriptorUtils.getJavaTypeFromBinaryName(
+ desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix());
+ String interfaceType = type.toString();
+ int firstPackage = interfaceType.indexOf('.');
+ return appView
+ .dexItemFactory()
+ .createType(
+ DescriptorUtils.javaTypeToDescriptor(
+ prefix + interfaceType.substring(firstPackage + 1)));
+ }
+ }
+ return null;
+ }
+
+ // Besides L8 compilation, program types should not be rewritten.
+ private void failIfRewritingProgramType(DexType type, AppView<?> appView) {
+ if (l8Compilation) {
+ return;
+ }
+
+ DexType dexType = type.isArrayType() ? type.toBaseType(appView.dexItemFactory()) : type;
+ DexClass dexClass = appView.definitionFor(dexType);
+ if (dexClass != null && dexClass.isProgramClass()) {
+ appView
+ .options()
+ .reporter
+ .error(
+ "Cannot compile program class "
+ + dexType
+ + " since it conflicts with a desugared library rewriting rule.");
+ }
+ }
+
+ @Override
+ public void rewriteType(DexType type, DexType rewrittenType) {
+ assert !notRewritten.contains(type)
+ : "New rewriting rule for "
+ + type
+ + " but the compiler has already made decisions based on the fact that this type was"
+ + " not rewritten";
+ assert !rewritten.containsKey(type) || rewritten.get(type) == rewrittenType
+ : "New rewriting rule for "
+ + type
+ + " but the compiler has already made decisions based on a different rewriting rule"
+ + " for this type";
+ rewritten.put(type, rewrittenType);
+ }
+
+ private DexType computePrefix(DexType type, AppView<?> appView) {
+ DexString prefixToMatch = type.descriptor.withoutArray(factory);
+ DexType result = lookup(type, prefixToMatch, initialPrefixes);
+ if (result != null) {
+ failIfRewritingProgramType(type, appView);
+ return result;
+ }
+ notRewritten.add(type);
+ return null;
+ }
+
+ private DexType lookup(DexType type, DexString prefixToMatch, Map<DexString, DexString> map) {
+ // TODO(b/154800164): We could use tries instead of looking-up everywhere.
+ for (DexString prefix : map.keySet()) {
+ if (prefixToMatch.startsWith(prefix)) {
+ DexString rewrittenTypeDescriptor =
+ type.descriptor.withNewPrefix(prefix, map.get(prefix), factory);
+ DexType rewrittenType = factory.createType(rewrittenTypeDescriptor);
+ rewriteType(type, rewrittenType);
+ return rewrittenType;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isRewriting() {
+ return true;
+ }
+ }
+
+ public static class MachineDesugarPrefixRewritingMapper extends PrefixRewritingMapper {
+
+ private final PrefixRewritingMapper mapper;
+ private final Map<DexType, DexType> rewriteType;
+ private final Map<DexType, DexType> rewriteDerivedTypeOnly;
+
+ public MachineDesugarPrefixRewritingMapper(
+ PrefixRewritingMapper mapper, MachineRewritingFlags flags) {
+ this.mapper = mapper;
+ this.rewriteType = new ConcurrentHashMap<>(flags.getRewriteType());
+ rewriteDerivedTypeOnly = flags.getRewriteDerivedTypeOnly();
+ }
+
+ @Override
+ public DexType rewrittenType(DexType type, AppView<?> appView) {
+ assert mapper.rewrittenType(type, appView) == rewriteType.get(type);
return rewriteType.get(type);
}
@Override
- public DexType rewrittenContextType(DexType context) {
- assert !context.isArrayType();
+ public DexType rewrittenContextType(DexType context, AppView<?> appView) {
if (rewriteType.containsKey(context)) {
return rewriteType.get(context);
}
@@ -80,6 +250,7 @@
@Override
public void rewriteType(DexType type, DexType rewrittenType) {
+ mapper.rewriteType(type, rewrittenType);
rewriteType.compute(
type,
(t, val) -> {
@@ -107,7 +278,7 @@
}
@Override
- public DexType rewrittenContextType(DexType type) {
+ public DexType rewrittenContextType(DexType type, AppView<?> appView) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java
index b66a96a..150e6c4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java
@@ -20,13 +20,13 @@
import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaring;
import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.desugaredlibrary.apiconversion.DesugaredLibraryWrapperSynthesizerEventConsumer.DesugaredLibraryAPICallbackSynthesizorEventConsumer;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APICallbackWrapperCfCodeProvider;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -109,8 +109,8 @@
if (!appView.rewritePrefix.hasRewrittenTypeInSignature(definition.getProto(), appView)
|| appView
.options()
- .machineDesugaredLibrarySpecification
- .getEmulatedInterfaces()
+ .desugaredLibrarySpecification
+ .getEmulateLibraryInterface()
.containsKey(method.getHolderType())) {
return false;
}
@@ -127,7 +127,7 @@
return false;
}
}
- if (!appView.options().machineDesugaredLibrarySpecification.supportAllCallbacksFromLibrary()
+ if (!appView.options().desugaredLibrarySpecification.supportAllCallbacksFromLibrary()
&& appView.options().isDesugaredLibraryCompilation()) {
return false;
}
@@ -178,13 +178,13 @@
}
private boolean shouldGenerateCallbacksForEmulateInterfaceAPIs(DexClass dexClass) {
- if (appView.options().machineDesugaredLibrarySpecification.supportAllCallbacksFromLibrary()) {
+ if (appView.options().desugaredLibrarySpecification.supportAllCallbacksFromLibrary()) {
return true;
}
- MachineDesugaredLibrarySpecification specification =
- appView.options().machineDesugaredLibrarySpecification;
- return !(specification.getEmulatedInterfaces().containsKey(dexClass.type)
- || specification.isEmulatedInterfaceRewrittenType(dexClass.type));
+ Map<DexType, DexType> emulateLibraryInterfaces =
+ appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface();
+ return !(emulateLibraryInterfaces.containsKey(dexClass.type)
+ || emulateLibraryInterfaces.containsValue(dexClass.type));
}
private ProgramMethod generateCallbackMethod(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
index f234a1b..987dc8d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
@@ -181,8 +181,8 @@
return interfaceResult != null
&& appView
.options()
- .machineDesugaredLibrarySpecification
- .getEmulatedInterfaces()
+ .desugaredLibrarySpecification
+ .getEmulateLibraryInterface()
.containsKey(interfaceResult.getHolderType());
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
index 71442ac..4a8cabe 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
@@ -13,14 +13,12 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexEncodedMember;
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.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.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
@@ -40,7 +38,6 @@
import com.android.tools.r8.synthesis.SyntheticClassBuilder;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
@@ -177,21 +174,17 @@
private DexMethod getCustomConversion(DexType type, DexType srcType, DexType destType) {
// ConversionType holds the methods "rewrittenType convert(type)" and the other way around.
// But everything is going to be rewritten, so we need to use vivifiedType and type".
- Pair<DexType, DexString> pair =
- appView.options().machineDesugaredLibrarySpecification.getCustomConversions().get(type);
- if (pair != null) {
+ DexType conversionHolder =
+ appView.options().desugaredLibrarySpecification.getCustomConversions().get(type);
+ if (conversionHolder != null) {
return factory.createMethod(
- pair.getFirst(), factory.createProto(destType, srcType), pair.getSecond());
+ conversionHolder, factory.createProto(destType, srcType), factory.convertMethodName);
}
return null;
}
private boolean canConvert(DexType type) {
- return appView
- .options()
- .machineDesugaredLibrarySpecification
- .getCustomConversions()
- .containsKey(type)
+ return appView.options().desugaredLibrarySpecification.getCustomConversions().containsKey(type)
|| canGenerateWrapper(type);
}
@@ -219,7 +212,7 @@
}
private boolean canGenerateWrapper(DexType type) {
- return appView.options().machineDesugaredLibrarySpecification.getWrappers().containsKey(type);
+ return appView.options().desugaredLibrarySpecification.getWrapperConversions().contains(type);
}
private DexClass getValidClassToWrap(DexType type) {
@@ -465,8 +458,9 @@
if (holderClass == null) {
assert appView
.options()
- .machineDesugaredLibrarySpecification
- .isEmulatedInterfaceRewrittenType(method.getHolderType());
+ .desugaredLibrarySpecification
+ .getEmulateLibraryInterface()
+ .containsValue(method.getHolderType());
isInterface = true;
} else {
isInterface = holderClass.isInterface();
@@ -547,17 +541,19 @@
}
private Iterable<DexMethod> allImplementedMethods(DexClass clazz) {
- if (appView.options().machineDesugaredLibrarySpecification != null) {
+ if (appView.options().testing.machineDesugaredLibrarySpecification != null) {
return appView
.options()
+ .testing
.machineDesugaredLibrarySpecification
+ .getRewritingFlags()
.getWrappers()
.get(clazz.type);
}
List<DexEncodedMethod> dexEncodedMethods =
allImplementedMethodsCache.computeIfAbsent(
clazz.type, type -> internalAllImplementedMethods(clazz));
- return Iterables.transform(dexEncodedMethods, DexEncodedMember::getReference);
+ return Iterables.transform(dexEncodedMethods, m -> m.getReference());
}
private List<DexEncodedMethod> internalAllImplementedMethods(DexClass libraryClass) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
index 1e871b3..6a6a2d4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
@@ -6,9 +6,14 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.DesugarPrefixRewritingMapper;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -18,20 +23,56 @@
private final boolean libraryCompilation;
private final HumanTopLevelFlags topLevelFlags;
private final HumanRewritingFlags rewritingFlags;
+ private final PrefixRewritingMapper prefixRewritingMapper;
+
+ public static HumanDesugaredLibrarySpecification withOnlyRewritePrefixForTesting(
+ Map<String, String> prefix, InternalOptions options) {
+ return new HumanDesugaredLibrarySpecification(
+ HumanTopLevelFlags.empty(),
+ HumanRewritingFlags.withOnlyRewritePrefixForTesting(prefix, options),
+ true,
+ options.itemFactory);
+ }
+
+ public static HumanDesugaredLibrarySpecification empty() {
+ return new HumanDesugaredLibrarySpecification(
+ HumanTopLevelFlags.empty(), HumanRewritingFlags.empty(), false, null) {
+
+ @Override
+ public boolean isSupported(DexReference reference, AppView<?> appView) {
+ return false;
+ }
+
+ @Override
+ public boolean isEmptyConfiguration() {
+ return true;
+ }
+ };
+ }
public HumanDesugaredLibrarySpecification(
HumanTopLevelFlags topLevelFlags,
HumanRewritingFlags rewritingFlags,
- boolean libraryCompilation) {
+ boolean libraryCompilation,
+ DexItemFactory factory) {
this.libraryCompilation = libraryCompilation;
this.topLevelFlags = topLevelFlags;
this.rewritingFlags = rewritingFlags;
+ this.prefixRewritingMapper =
+ rewritingFlags.getRewritePrefix().isEmpty()
+ ? PrefixRewritingMapper.empty()
+ : new DesugarPrefixRewritingMapper(
+ rewritingFlags.getRewritePrefix(), factory, libraryCompilation);
}
public boolean supportAllCallbacksFromLibrary() {
return topLevelFlags.supportAllCallbacksFromLibrary();
}
+ public PrefixRewritingMapper getPrefixRewritingMapper() {
+ return prefixRewritingMapper;
+ }
+
public AndroidApiLevel getRequiredCompilationApiLevel() {
return topLevelFlags.getRequiredCompilationAPILevel();
}
@@ -68,6 +109,10 @@
return rewritingFlags.getEmulateLibraryInterface();
}
+ public boolean isSupported(DexReference reference, AppView<?> appView) {
+ return prefixRewritingMapper.hasRewrittenType(reference.getContextType(), appView);
+ }
+
// If the method is retargeted, answers the retargeted method, else null.
public DexMethod retargetMethod(DexEncodedMethod method, AppView<?> appView) {
Map<DexMethod, DexType> retargetCoreLibMember = rewritingFlags.getRetargetCoreLibMember();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
index e01def6..a612177 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
@@ -103,7 +103,7 @@
HumanDesugaredLibrarySpecification config =
new HumanDesugaredLibrarySpecification(
- topLevelFlags, legacyRewritingFlags, libraryCompilation);
+ topLevelFlags, legacyRewritingFlags, libraryCompilation, dexItemFactory);
origin = null;
return config;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java
index 9ab05b9..3da0b97 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecification.java
@@ -6,9 +6,13 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.DesugarPrefixRewritingMapper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -22,18 +26,25 @@
private final boolean libraryCompilation;
private final LegacyTopLevelFlags topLevelFlags;
private final LegacyRewritingFlags rewritingFlags;
+ private final PrefixRewritingMapper prefixRewritingMapper;
public static LegacyDesugaredLibrarySpecification withOnlyRewritePrefixForTesting(
Map<String, String> prefix, InternalOptions options) {
return new LegacyDesugaredLibrarySpecification(
LegacyTopLevelFlags.empty(),
LegacyRewritingFlags.withOnlyRewritePrefixForTesting(prefix, options),
- true);
+ true,
+ options.itemFactory);
}
public static LegacyDesugaredLibrarySpecification empty() {
return new LegacyDesugaredLibrarySpecification(
- LegacyTopLevelFlags.empty(), LegacyRewritingFlags.empty(), false) {
+ LegacyTopLevelFlags.empty(), LegacyRewritingFlags.empty(), false, null) {
+
+ @Override
+ public boolean isSupported(DexReference reference, AppView<?> appView) {
+ return false;
+ }
@Override
public boolean isEmptyConfiguration() {
@@ -45,10 +56,16 @@
public LegacyDesugaredLibrarySpecification(
LegacyTopLevelFlags topLevelFlags,
LegacyRewritingFlags rewritingFlags,
- boolean libraryCompilation) {
+ boolean libraryCompilation,
+ DexItemFactory factory) {
this.libraryCompilation = libraryCompilation;
this.topLevelFlags = topLevelFlags;
this.rewritingFlags = rewritingFlags;
+ this.prefixRewritingMapper =
+ rewritingFlags.getRewritePrefix().isEmpty()
+ ? PrefixRewritingMapper.empty()
+ : new DesugarPrefixRewritingMapper(
+ rewritingFlags.getRewritePrefix(), factory, libraryCompilation);
}
public LegacyTopLevelFlags getTopLevelFlags() {
@@ -63,6 +80,10 @@
return topLevelFlags.supportAllCallbacksFromLibrary();
}
+ public PrefixRewritingMapper getPrefixRewritingMapper() {
+ return prefixRewritingMapper;
+ }
+
public AndroidApiLevel getRequiredCompilationApiLevel() {
return topLevelFlags.getRequiredCompilationAPILevel();
}
@@ -102,6 +123,10 @@
return rewritingFlags.getEmulateLibraryInterface();
}
+ public boolean isSupported(DexReference reference, AppView<?> appView) {
+ return prefixRewritingMapper.hasRewrittenType(reference.getContextType(), appView);
+ }
+
// If the method is retargeted, answers the retargeted method, else null.
public DexMethod retargetMethod(DexEncodedMethod method, AppView<?> appView) {
Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecificationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecificationParser.java
index a3afcd9..7cece17 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecificationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/legacyspecification/LegacyDesugaredLibrarySpecificationParser.java
@@ -110,7 +110,7 @@
LegacyDesugaredLibrarySpecification config =
new LegacyDesugaredLibrarySpecification(
- topLevelFlags, legacyRewritingFlags, libraryCompilation);
+ topLevelFlags, legacyRewritingFlags, libraryCompilation, dexItemFactory);
origin = null;
return config;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
index e1368e3..501482e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
@@ -4,41 +4,12 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexReference;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.Pair;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Consumer;
-
public class MachineDesugaredLibrarySpecification {
private final boolean libraryCompilation;
private final MachineTopLevelFlags topLevelFlags;
private final MachineRewritingFlags rewritingFlags;
- public static MachineDesugaredLibrarySpecification empty() {
- return new MachineDesugaredLibrarySpecification(
- false, MachineTopLevelFlags.empty(), MachineRewritingFlags.builder().build()) {
- @Override
- public boolean isSupported(DexReference reference) {
- return false;
- }
- };
- }
-
- public static MachineDesugaredLibrarySpecification withOnlyRewriteTypeForTesting(
- Map<DexType, DexType> rewriteTypeForTesting) {
- MachineRewritingFlags.Builder builder = MachineRewritingFlags.builder();
- rewriteTypeForTesting.forEach(builder::rewriteType);
- return new MachineDesugaredLibrarySpecification(
- true, MachineTopLevelFlags.empty(), builder.build());
- }
-
public MachineDesugaredLibrarySpecification(
boolean libraryCompilation,
MachineTopLevelFlags topLevelFlags,
@@ -52,116 +23,11 @@
return libraryCompilation;
}
- public AndroidApiLevel getRequiredCompilationAPILevel() {
- return topLevelFlags.getRequiredCompilationAPILevel();
+ public MachineTopLevelFlags getTopLevelFlags() {
+ return topLevelFlags;
}
- public String getSynthesizedLibraryClassesPackagePrefix() {
- return topLevelFlags.getSynthesizedLibraryClassesPackagePrefix();
- }
-
- public String getIdentifier() {
- return topLevelFlags.getIdentifier();
- }
-
- public String getJsonSource() {
- return topLevelFlags.getJsonSource();
- }
-
- public boolean supportAllCallbacksFromLibrary() {
- return topLevelFlags.supportAllCallbacksFromLibrary();
- }
-
- public List<String> getExtraKeepRules() {
- return topLevelFlags.getExtraKeepRules();
- }
-
- public Map<DexType, DexType> getRewriteType() {
- return rewritingFlags.getRewriteType();
- }
-
- public Map<DexType, DexType> getRewriteDerivedTypeOnly() {
- return rewritingFlags.getRewriteDerivedTypeOnly();
- }
-
- public Map<DexMethod, DexMethod> getStaticRetarget() {
- return rewritingFlags.getStaticRetarget();
- }
-
- public Map<DexMethod, DexMethod> getNonEmulatedVirtualRetarget() {
- return rewritingFlags.getNonEmulatedVirtualRetarget();
- }
-
- public Map<DexMethod, EmulatedDispatchMethodDescriptor> getEmulatedVirtualRetarget() {
- return rewritingFlags.getEmulatedVirtualRetarget();
- }
-
- public void forEachRetargetHolder(Consumer<DexType> consumer) {
- rewritingFlags.forEachRetargetHolder(consumer);
- }
-
- public Map<DexType, EmulatedInterfaceDescriptor> getEmulatedInterfaces() {
- return rewritingFlags.getEmulatedInterfaces();
- }
-
- public EmulatedDispatchMethodDescriptor getEmulatedInterfaceEmulatedDispatchMethodDescriptor(
- DexMethod method) {
- return rewritingFlags.getEmulatedInterfaceEmulatedDispatchMethodDescriptor(method);
- }
-
- public boolean isCustomConversionRewrittenType(DexType type) {
- return rewritingFlags.isCustomConversionRewrittenType(type);
- }
-
- public boolean isEmulatedInterfaceRewrittenType(DexType type) {
- return rewritingFlags.isEmulatedInterfaceRewrittenType(type);
- }
-
- public Map<DexType, List<DexMethod>> getWrappers() {
- return rewritingFlags.getWrappers();
- }
-
- public Map<DexType, DexType> getLegacyBackport() {
- return rewritingFlags.getLegacyBackport();
- }
-
- public Set<DexType> getDontRetarget() {
- return rewritingFlags.getDontRetarget();
- }
-
- public Map<DexType, Pair<DexType, DexString>> getCustomConversions() {
- return rewritingFlags.getCustomConversions();
- }
-
- public boolean hasRetargeting() {
- return rewritingFlags.hasRetargeting();
- }
-
- public boolean hasEmulatedInterfaces() {
- return rewritingFlags.hasEmulatedInterfaces();
- }
-
- public boolean isSupported(DexReference reference) {
- // Support through type rewriting.
- if (rewritingFlags.getRewriteType().containsKey(reference.getContextType())) {
- return true;
- }
- if (!reference.isDexMethod()) {
- return false;
- }
- // Support through retargeting.
- DexMethod dexMethod = reference.asDexMethod();
- if (getStaticRetarget().containsKey(dexMethod)
- || getNonEmulatedVirtualRetarget().containsKey(dexMethod)
- || getEmulatedVirtualRetarget().containsKey(dexMethod)) {
- return true;
- }
- // Support through emulated interface.
- for (EmulatedInterfaceDescriptor descriptor : getEmulatedInterfaces().values()) {
- if (descriptor.getEmulatedMethods().containsKey(dexMethod)) {
- return true;
- }
- }
- return false;
+ public MachineRewritingFlags getRewritingFlags() {
+ return rewritingFlags;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
index c5c77c6..a6c487e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
@@ -11,12 +11,10 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.function.Consumer;
public class MachineRewritingFlags {
@@ -96,12 +94,6 @@
return emulatedVirtualRetarget;
}
- public void forEachRetargetHolder(Consumer<DexType> consumer) {
- staticRetarget.keySet().forEach(m -> consumer.accept(m.getHolderType()));
- nonEmulatedVirtualRetarget.keySet().forEach(m -> consumer.accept(m.getHolderType()));
- emulatedVirtualRetarget.keySet().forEach(m -> consumer.accept(m.getHolderType()));
- }
-
public Map<DexType, EmulatedInterfaceDescriptor> getEmulatedInterfaces() {
return emulatedInterfaces;
}
@@ -118,37 +110,10 @@
return dontRetarget;
}
- public boolean isCustomConversionRewrittenType(DexType type) {
- return Iterables.any(customConversions.values(), pair -> pair.getFirst() == type);
- }
-
public Map<DexType, Pair<DexType, DexString>> getCustomConversions() {
return customConversions;
}
- public boolean hasRetargeting() {
- return !staticRetarget.isEmpty()
- || !nonEmulatedVirtualRetarget.isEmpty()
- || !emulatedVirtualRetarget.isEmpty();
- }
-
- public boolean isEmulatedInterfaceRewrittenType(DexType type) {
- return Iterables.any(
- emulatedInterfaces.values(), descriptor -> descriptor.getRewrittenType() == type);
- }
-
- public boolean hasEmulatedInterfaces() {
- return !emulatedInterfaces.isEmpty();
- }
-
- EmulatedDispatchMethodDescriptor getEmulatedInterfaceEmulatedDispatchMethodDescriptor(
- DexMethod method) {
- if (!emulatedInterfaces.containsKey(method.getHolderType())) {
- return null;
- }
- return emulatedInterfaces.get(method.getHolderType()).getEmulatedMethods().get(method);
- }
-
public static class Builder {
Builder() {}
@@ -172,7 +137,6 @@
public void rewriteType(DexType src, DexType target) {
assert src != null;
assert target != null;
- assert src != target;
rewriteType.put(src, target);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java
index 0c6a88a..f426219 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.google.common.collect.ImmutableList;
import java.util.List;
public class MachineTopLevelFlags {
@@ -24,11 +23,6 @@
private final boolean supportAllCallbacksFromLibrary;
private final List<String> extraKeepRules;
- public static MachineTopLevelFlags empty() {
- return new MachineTopLevelFlags(
- AndroidApiLevel.B, "unused", null, null, false, ImmutableList.of());
- }
-
public MachineTopLevelFlags(
AndroidApiLevel requiredCompilationAPILevel,
String synthesizedLibraryClassesPackagePrefix,
@@ -60,7 +54,7 @@
return jsonSource;
}
- public boolean supportAllCallbacksFromLibrary() {
+ public boolean isSupportAllCallbacksFromLibrary() {
return supportAllCallbacksFromLibrary;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
index 5fcf037..a54cd8d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
@@ -129,8 +129,8 @@
}
if (appView
.options()
- .machineDesugaredLibrarySpecification
- .getDontRetarget()
+ .desugaredLibrarySpecification
+ .getDontRetargetLibMember()
.contains(context.getContextType())) {
return NO_REWRITING;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java
index eb28d20..11fcfb7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java
@@ -20,7 +20,7 @@
AppView<?> appView, RetargetingInfo retargetingInfo) {
assert appView.options().isDesugaredLibraryCompilation();
if (retargetingInfo == null || retargetingInfo.getEmulatedVirtualRetarget().isEmpty()) {
- assert !appView.options().machineDesugaredLibrarySpecification.hasRetargeting();
+ assert appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty();
return null;
}
return new DesugaredLibraryRetargeterL8Synthesizer(appView, retargetingInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java
index bfb423a..bbaa4cf 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java
@@ -39,16 +39,16 @@
public class DesugaredLibraryRetargeterLibraryTypeSynthesizer {
public static void checkForAssumedLibraryTypes(AppView<?> appView) {
- appView
- .options()
- .machineDesugaredLibrarySpecification
- .forEachRetargetHolder(
- inType -> {
- DexClass typeClass = appView.definitionFor(inType);
- if (typeClass == null) {
- warnMissingRetargetCoreLibraryMember(inType, appView);
- }
- });
+ Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+ appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember();
+ for (DexString methodName : retargetCoreLibMember.keySet()) {
+ for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+ DexClass typeClass = appView.definitionFor(inType);
+ if (typeClass == null) {
+ warnMissingRetargetCoreLibraryMember(inType, appView);
+ }
+ }
+ }
}
public static void amendLibraryWithRetargetedMembers(AppView<AppInfoWithClassHierarchy> appView) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java
index d1e64ec..414c32d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java
@@ -127,8 +127,8 @@
}
if (appView
.options()
- .machineDesugaredLibrarySpecification
- .getDontRetarget()
+ .desugaredLibrarySpecification
+ .getDontRetargetLibMember()
.contains(clazz.getType())) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java
index b7ac366..9e1f5e3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java
@@ -4,9 +4,24 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.WorkList;
+import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
public class RetargetingInfo {
@@ -25,12 +40,15 @@
}
public static RetargetingInfo get(AppView<?> appView) {
- MachineDesugaredLibrarySpecification specification =
- appView.options().machineDesugaredLibrarySpecification;
- return new RetargetingInfo(
- specification.getStaticRetarget(),
- specification.getNonEmulatedVirtualRetarget(),
- specification.getEmulatedVirtualRetarget());
+ if (appView.options().testing.machineDesugaredLibrarySpecification != null) {
+ MachineRewritingFlags rewritingFlags =
+ appView.options().testing.machineDesugaredLibrarySpecification.getRewritingFlags();
+ return new RetargetingInfo(
+ rewritingFlags.getStaticRetarget(),
+ rewritingFlags.getNonEmulatedVirtualRetarget(),
+ rewritingFlags.getEmulatedVirtualRetarget());
+ }
+ return new RetargetingInfoBuilder(appView).computeRetargetingInfo();
}
public Map<DexMethod, DexMethod> getStaticRetarget() {
@@ -44,4 +62,152 @@
public Map<DexMethod, EmulatedDispatchMethodDescriptor> getEmulatedVirtualRetarget() {
return emulatedVirtualRetarget;
}
+
+ private static class RetargetingInfoBuilder {
+
+ private final AppView<?> appView;
+ private final Map<DexMethod, DexMethod> staticRetarget = new IdentityHashMap<>();
+ private final Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget = new IdentityHashMap<>();
+ private final Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedVirtualRetarget =
+ new IdentityHashMap<>();
+
+ public RetargetingInfoBuilder(AppView<?> appView) {
+ this.appView = appView;
+ }
+
+ private RetargetingInfo computeRetargetingInfo() {
+ LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
+ appView.options().desugaredLibrarySpecification;
+ Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+ desugaredLibrarySpecification.getRetargetCoreLibMember();
+ if (retargetCoreLibMember.isEmpty()) {
+ return new RetargetingInfo(ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of());
+ }
+ for (DexString methodName : retargetCoreLibMember.keySet()) {
+ for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+ DexClass typeClass = appView.definitionFor(inType);
+ if (typeClass != null) {
+ DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
+ List<DexClassAndMethod> found = findMethodsWithName(methodName, typeClass);
+ for (DexClassAndMethod method : found) {
+ DexMethod methodReference = method.getReference();
+ if (method.getAccessFlags().isStatic()) {
+ staticRetarget.put(
+ methodReference,
+ computeRetargetMethod(
+ methodReference, method.getAccessFlags().isStatic(), newHolder));
+ continue;
+ }
+ if (isEmulatedInterfaceDispatch(method)) {
+ continue;
+ }
+ if (typeClass.isFinal() || method.getAccessFlags().isFinal()) {
+ nonEmulatedVirtualRetarget.put(
+ methodReference,
+ computeRetargetMethod(
+ methodReference, method.getAccessFlags().isStatic(), newHolder));
+ } else {
+ // Virtual rewrites require emulated dispatch for inheritance.
+ // The call is rewritten to the dispatch holder class instead.
+ DexProto newProto = appView.dexItemFactory().prependHolderToProto(methodReference);
+ DexMethod forwardingDexMethod =
+ appView.dexItemFactory().createMethod(newHolder, newProto, methodName);
+ DerivedMethod forwardingMethod = new DerivedMethod(forwardingDexMethod);
+ DerivedMethod interfaceMethod =
+ new DerivedMethod(methodReference, SyntheticKind.RETARGET_INTERFACE);
+ DerivedMethod dispatchMethod =
+ new DerivedMethod(methodReference, SyntheticKind.RETARGET_CLASS);
+ emulatedVirtualRetarget.put(
+ methodReference,
+ new EmulatedDispatchMethodDescriptor(
+ interfaceMethod, dispatchMethod, forwardingMethod, new LinkedHashMap<>()));
+ }
+ }
+ }
+ }
+ }
+ if (desugaredLibrarySpecification.isLibraryCompilation()) {
+ // TODO(b/177977763): This is only a workaround rewriting invokes of j.u.Arrays.deepEquals0
+ // to j.u.DesugarArrays.deepEquals0.
+ DexItemFactory itemFactory = appView.options().dexItemFactory();
+ DexString name = itemFactory.createString("deepEquals0");
+ DexProto proto =
+ itemFactory.createProto(
+ itemFactory.booleanType, itemFactory.objectType, itemFactory.objectType);
+ DexMethod source =
+ itemFactory.createMethod(
+ itemFactory.createType(itemFactory.arraysDescriptor), proto, name);
+ DexMethod target =
+ computeRetargetMethod(
+ source, true, itemFactory.createType("Ljava/util/DesugarArrays;"));
+ staticRetarget.put(source, target);
+ // TODO(b/181629049): This is only a workaround rewriting invokes of
+ // j.u.TimeZone.getTimeZone taking a java.time.ZoneId.
+ name = itemFactory.createString("getTimeZone");
+ proto =
+ itemFactory.createProto(
+ itemFactory.createType("Ljava/util/TimeZone;"),
+ itemFactory.createType("Ljava/time/ZoneId;"));
+ source =
+ itemFactory.createMethod(itemFactory.createType("Ljava/util/TimeZone;"), proto, name);
+ target =
+ computeRetargetMethod(
+ source, true, itemFactory.createType("Ljava/util/DesugarTimeZone;"));
+ staticRetarget.put(source, target);
+ }
+ return new RetargetingInfo(
+ ImmutableMap.copyOf(staticRetarget),
+ ImmutableMap.copyOf(nonEmulatedVirtualRetarget),
+ emulatedVirtualRetarget);
+ }
+
+ DexMethod computeRetargetMethod(DexMethod method, boolean isStatic, DexType newHolder) {
+ DexItemFactory factory = appView.dexItemFactory();
+ DexProto newProto = isStatic ? method.getProto() : factory.prependHolderToProto(method);
+ return factory.createMethod(newHolder, newProto, method.getName());
+ }
+
+ private boolean isEmulatedInterfaceDispatch(DexClassAndMethod method) {
+ // Answers true if this method is already managed through emulated interface dispatch.
+ Map<DexType, DexType> emulateLibraryInterface =
+ appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface();
+ if (emulateLibraryInterface.isEmpty()) {
+ return false;
+ }
+ DexMethod methodToFind = method.getReference();
+ // Look-up all superclass and interfaces, if an emulated interface is found, and it implements
+ // the method, answers true.
+ WorkList<DexClass> worklist = WorkList.newIdentityWorkList(method.getHolder());
+ while (worklist.hasNext()) {
+ DexClass clazz = worklist.next();
+ if (clazz.isInterface()
+ && emulateLibraryInterface.containsKey(clazz.getType())
+ && clazz.lookupMethod(methodToFind) != null) {
+ return true;
+ }
+ // All super types are library class, or we are doing L8 compilation.
+ clazz.forEachImmediateSupertype(
+ superType -> {
+ DexClass superClass = appView.definitionFor(superType);
+ if (superClass != null) {
+ worklist.addIfNotSeen(superClass);
+ }
+ });
+ }
+ return false;
+ }
+
+ private List<DexClassAndMethod> findMethodsWithName(DexString methodName, DexClass clazz) {
+ List<DexClassAndMethod> found = new ArrayList<>();
+ clazz.forEachClassMethodMatching(
+ definition -> definition.getName() == methodName, found::add);
+ assert !found.isEmpty()
+ : "Should have found a method (library specifications) for "
+ + clazz.toSourceString()
+ + "."
+ + methodName
+ + ". Maybe the library used for the compilation should be newer.";
+ return found;
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
index 04cc12b..2411ba0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
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.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
@@ -43,10 +44,10 @@
Set<DexMethod> dontRewriteInvocation = rewritingFlags.getDontRewriteInvocation();
emulatedInterfaceHierarchy = processEmulatedInterfaceHierarchy(appInfo, emulateInterfaces);
for (DexType itf : emulateInterfaces.keySet()) {
- DexClass itfClass = appInfo.contextIndependentDefinitionFor(itf);
+ DexProgramClass itfClass = appInfo.contextIndependentDefinitionFor(itf).asProgramClass();
assert itfClass != null;
Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedMethods = new IdentityHashMap<>();
- itfClass.forEachClassMethodMatching(
+ itfClass.forEachProgramVirtualMethodMatching(
m -> m.isDefaultMethod() && !dontRewriteInvocation.contains(m.getReference()),
method ->
emulatedMethods.put(
@@ -103,6 +104,7 @@
for (int i = subInterfaces.size() - 1; i >= 0; i--) {
DexClass subInterfaceClass = appInfo.definitionFor(subInterfaces.get(i));
assert subInterfaceClass != null;
+ assert subInterfaceClass.isProgramClass();
// Else computation of subInterface would have failed.
// if the method is implemented, extra dispatch is required.
DexEncodedMethod result = subInterfaceClass.lookupVirtualMethod(method);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
index 92efb24..6ff7428 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
@@ -5,31 +5,22 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableMap;
-import java.util.IdentityHashMap;
import java.util.Map;
public class HumanToMachinePrefixConverter {
private final AppInfoWithClassHierarchy appInfo;
- private final MachineRewritingFlags.Builder builder;
- private final String synthesizedPrefix;
- private final Map<DexType, DexType> reverse = new IdentityHashMap<>();
- public HumanToMachinePrefixConverter(
- AppInfoWithClassHierarchy appInfo,
- MachineRewritingFlags.Builder builder,
- String synthesizedPrefix) {
+ public HumanToMachinePrefixConverter(AppInfoWithClassHierarchy appInfo) {
this.appInfo = appInfo;
- this.builder = builder;
- this.synthesizedPrefix = synthesizedPrefix;
}
private DexString toDescriptorPrefix(String prefix) {
@@ -38,30 +29,20 @@
.createString("L" + DescriptorUtils.getBinaryNameFromJavaType(prefix));
}
- public void convertPrefixFlags(HumanRewritingFlags rewritingFlags) {
+ public void convertPrefixFlags(
+ HumanRewritingFlags rewritingFlags,
+ MachineRewritingFlags.Builder builder,
+ String synthesizedPrefix) {
Map<DexString, DexString> descriptorPrefix = convertRewritePrefix(rewritingFlags);
- rewriteClasses(descriptorPrefix);
- rewriteValues(descriptorPrefix, rewritingFlags.getRetargetCoreLibMember());
- rewriteValues(descriptorPrefix, rewritingFlags.getCustomConversions());
- rewriteEmulatedInterface(rewritingFlags.getEmulateLibraryInterface());
- rewriteRetargetKeys(rewritingFlags.getRetargetCoreLibMember());
- rewriteReverse(descriptorPrefix);
+ rewriteClasses(descriptorPrefix, builder);
+ rewriteValues(descriptorPrefix, builder, rewritingFlags.getRetargetCoreLibMember());
+ rewriteValues(descriptorPrefix, builder, rewritingFlags.getCustomConversions());
+ rewriteEmulatedInterface(builder, rewritingFlags.getEmulateLibraryInterface());
+ rewriteRetargetKeys(builder, rewritingFlags.getRetargetCoreLibMember(), synthesizedPrefix);
}
- // For custom conversions, this is responsible in rewriting backward.
- private void rewriteReverse(Map<DexString, DexString> descriptorPrefix) {
- reverse.forEach(
- (rewrittenType, type) -> {
- DexType backwardRewrittenType = rewrittenType(descriptorPrefix, rewrittenType);
- if (backwardRewrittenType != null) {
- assert backwardRewrittenType == type;
- builder.rewriteType(rewrittenType, type);
- }
- });
- }
-
- public DexType convertJavaNameToDesugaredLibrary(DexType type) {
- String convertedPrefix = DescriptorUtils.getJavaTypeFromBinaryName(synthesizedPrefix);
+ public DexType convertJavaNameToDesugaredLibrary(DexType type, String prefix) {
+ String convertedPrefix = DescriptorUtils.getJavaTypeFromBinaryName(prefix);
String interfaceType = type.toString();
int firstPackage = interfaceType.indexOf('.');
return appInfo
@@ -71,49 +52,40 @@
convertedPrefix + interfaceType.substring(firstPackage + 1)));
}
- private void rewriteRetargetKeys(Map<DexMethod, DexType> retarget) {
+ private void rewriteRetargetKeys(
+ MachineRewritingFlags.Builder builder, Map<DexMethod, DexType> retarget, String prefix) {
for (DexMethod dexMethod : retarget.keySet()) {
- DexType type = convertJavaNameToDesugaredLibrary(dexMethod.holder);
+ DexType type = convertJavaNameToDesugaredLibrary(dexMethod.holder, prefix);
builder.rewriteDerivedTypeOnly(dexMethod.holder, type);
}
}
- private void rewriteEmulatedInterface(Map<DexType, DexType> emulateLibraryInterface) {
+ private void rewriteEmulatedInterface(
+ MachineRewritingFlags.Builder builder, Map<DexType, DexType> emulateLibraryInterface) {
emulateLibraryInterface.forEach(builder::rewriteDerivedTypeOnly);
}
- private void rewriteType(DexType type, DexType rewrittenType) {
- builder.rewriteType(type, rewrittenType);
- reverse.put(rewrittenType, type);
- }
-
private void rewriteValues(
Map<DexString, DexString> descriptorPrefix,
+ MachineRewritingFlags.Builder builder,
Map<?, DexType> flags) {
for (DexType type : flags.values()) {
DexType rewrittenType = rewrittenType(descriptorPrefix, type);
if (rewrittenType != null) {
- rewriteType(type, rewrittenType);
+ builder.rewriteType(type, rewrittenType);
}
}
}
- private void rewriteClasses(Map<DexString, DexString> descriptorPrefix) {
- for (DexClass clazz : appInfo.app().asDirect().libraryClasses()) {
- rewriteClass(descriptorPrefix, clazz);
+ private void rewriteClasses(
+ Map<DexString, DexString> descriptorPrefix, MachineRewritingFlags.Builder builder) {
+ for (DexProgramClass clazz : appInfo.classes()) {
+ DexType type = clazz.type;
+ DexType rewrittenType = rewrittenType(descriptorPrefix, type);
+ if (rewrittenType != null) {
+ builder.rewriteType(type, rewrittenType);
+ }
}
- for (DexClass clazz : appInfo.classes()) {
- rewriteClass(descriptorPrefix, clazz);
- }
- }
-
- private void rewriteClass(Map<DexString, DexString> descriptorPrefix, DexClass clazz) {
- DexType type = clazz.type;
- DexType rewrittenType = rewrittenType(descriptorPrefix, type);
- if (rewrittenType == null) {
- return;
- }
- rewriteType(type, rewrittenType);
}
private DexType rewrittenType(Map<DexString, DexString> descriptorPrefix, DexType type) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
index b5c1ac3..6dce945 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
@@ -92,14 +92,10 @@
DexClass subclass = appInfo.definitionFor(subtype);
MethodResolutionResult resolutionResult =
appInfo.resolveMethodOn(subclass, src.getReference());
- // The resolution is not successful when compiling to dex if the method rewritten is missing
- // in Android.jar.
- assert !resolutionResult.isSuccessfulMemberResolutionResult()
- || resolutionResult.getResolvedMethod().getReference() == src.getReference()
- // There is a difference in the sql library between Android.jar and the JDK which leads
- // to this resolution when compiling Cf to Cf while the methods do not exist in Android.
- || (resolutionResult.getResolvedMethod().getHolderType().toString().contains("java.sql")
- && resolutionResult.getResolvedMethod().getName().toString().equals("toInstant"));
+ if (resolutionResult.isSuccessfulMemberResolutionResult()
+ && resolutionResult.getResolvedMethod().getReference() != src.getReference()) {
+ assert false; // Unsupported.
+ }
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
index 23824c5..bc3a663 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
-import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -24,51 +22,15 @@
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.nio.file.Path;
-import java.util.List;
import java.util.concurrent.ExecutorService;
public class HumanToMachineSpecificationConverter {
public MachineDesugaredLibrarySpecification convert(
- HumanDesugaredLibrarySpecification humanSpec,
- List<ProgramResourceProvider> desugaredJDKLib,
- List<ClassFileResourceProvider> library,
- InternalOptions options)
+ HumanDesugaredLibrarySpecification humanSpec, Path androidLib, InternalOptions options)
throws IOException {
- assert !humanSpec.isLibraryCompilation() || desugaredJDKLib != null;
- AndroidApp.Builder builder = AndroidApp.builder();
- for (ClassFileResourceProvider classFileResourceProvider : library) {
- builder.addLibraryResourceProvider(classFileResourceProvider);
- }
- if (humanSpec.isLibraryCompilation()) {
- for (ProgramResourceProvider programResourceProvider : desugaredJDKLib) {
- builder.addProgramResourceProvider(programResourceProvider);
- }
- }
- return internalConvert(humanSpec, builder.build(), options);
- }
-
- public MachineDesugaredLibrarySpecification convert(
- HumanDesugaredLibrarySpecification humanSpec,
- Path desugaredJDKLib,
- Path androidLib,
- InternalOptions options)
- throws IOException {
- assert !humanSpec.isLibraryCompilation() || desugaredJDKLib != null;
- AndroidApp.Builder builder = AndroidApp.builder();
- if (humanSpec.isLibraryCompilation()) {
- builder.addProgramFile(desugaredJDKLib);
- }
- AndroidApp inputApp = builder.addLibraryFile(androidLib).build();
- return internalConvert(humanSpec, inputApp, options);
- }
-
- public MachineDesugaredLibrarySpecification internalConvert(
- HumanDesugaredLibrarySpecification humanSpec, AndroidApp inputApp, InternalOptions options)
- throws IOException {
- DexApplication app = readApp(inputApp, options);
+ DexApplication app = readApp(androidLib, options);
AppView<?> appView = AppView.createForD8(AppInfo.createInitialAppInfo(app));
- LibraryValidator.validate(app, humanSpec.getTopLevelFlags().getRequiredCompilationAPILevel());
MachineRewritingFlags machineRewritingFlags =
convertRewritingFlags(
humanSpec.getSynthesizedLibraryClassesPackagePrefix(),
@@ -97,8 +59,8 @@
new HumanToMachineRetargetConverter(appInfo).convertRetargetFlags(rewritingFlags, builder);
new HumanToMachineEmulatedInterfaceConverter(appInfo)
.convertEmulatedInterfaces(rewritingFlags, appInfo, builder);
- new HumanToMachinePrefixConverter(appInfo, builder, synthesizedPrefix)
- .convertPrefixFlags(rewritingFlags);
+ new HumanToMachinePrefixConverter(appInfo)
+ .convertPrefixFlags(rewritingFlags, builder, synthesizedPrefix);
new HumanToMachineWrapperConverter(appInfo).convertWrappers(rewritingFlags, builder);
rewritingFlags
.getCustomConversions()
@@ -113,8 +75,10 @@
return builder.build();
}
- private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
- ApplicationReader applicationReader = new ApplicationReader(inputApp, options, Timing.empty());
+ private DexApplication readApp(Path androidLib, InternalOptions options) throws IOException {
+ AndroidApp androidApp = AndroidApp.builder().addProgramFile(androidLib).build();
+ ApplicationReader applicationReader =
+ new ApplicationReader(androidApp, options, Timing.empty());
ExecutorService executorService = ThreadUtils.getExecutorService(options);
return applicationReader.read(executorService).toDirect();
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
index e5c9b42..34bf5fa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
-import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.dex.ApplicationReader;
@@ -66,9 +65,7 @@
InternalOptions options)
throws IOException {
Origin origin = legacySpec.getOrigin();
- AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
- DexApplication app = readApp(androidApp, options);
- LibraryValidator.validate(app, legacySpec.getTopLevelFlags().getRequiredCompilationAPILevel());
+ DexApplication app = readApp(androidLib, options);
HumanTopLevelFlags humanTopLevelFlags = convertTopLevelFlags(legacySpec.getTopLevelFlags());
Int2ObjectArrayMap<HumanRewritingFlags> commonFlags =
convertRewritingFlagMap(legacySpec.getCommonFlags(), app, origin);
@@ -84,30 +81,11 @@
}
public HumanDesugaredLibrarySpecification convert(
- LegacyDesugaredLibrarySpecification legacySpec,
- List<ClassFileResourceProvider> library,
- InternalOptions options)
- throws IOException {
- AndroidApp.Builder builder = AndroidApp.builder();
- for (ClassFileResourceProvider classFileResourceProvider : library) {
- builder.addLibraryResourceProvider(classFileResourceProvider);
- }
- return internalConvert(legacySpec, builder.build(), options);
- }
-
- public HumanDesugaredLibrarySpecification convert(
LegacyDesugaredLibrarySpecification legacySpec, Path androidLib, InternalOptions options)
throws IOException {
- AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
- return internalConvert(legacySpec, androidApp, options);
- }
-
- public HumanDesugaredLibrarySpecification internalConvert(
- LegacyDesugaredLibrarySpecification legacySpec, AndroidApp inputApp, InternalOptions options)
- throws IOException {
- DexApplication app = readApp(inputApp, options);
- LibraryValidator.validate(app, legacySpec.getTopLevelFlags().getRequiredCompilationAPILevel());
+ DexApplication app = readApp(androidLib, options);
HumanTopLevelFlags humanTopLevelFlags = convertTopLevelFlags(legacySpec.getTopLevelFlags());
+
// The origin is not maintained in non multi-level specifications.
// It should not matter since the origin is used to report invalid specifications, and
// converting non multi-level specifications should be performed only with *valid*
@@ -117,7 +95,10 @@
HumanRewritingFlags humanRewritingFlags =
convertRewritingFlags(legacySpec.getRewritingFlags(), app, origin);
return new HumanDesugaredLibrarySpecification(
- humanTopLevelFlags, humanRewritingFlags, legacySpec.isLibraryCompilation());
+ humanTopLevelFlags,
+ humanRewritingFlags,
+ legacySpec.isLibraryCompilation(),
+ app.dexItemFactory());
}
private void legacyLibraryFlagHacks(
@@ -153,8 +134,10 @@
libraryFlags.put(level, builder.build());
}
- private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
- ApplicationReader applicationReader = new ApplicationReader(inputApp, options, Timing.empty());
+ private DexApplication readApp(Path androidLib, InternalOptions options) throws IOException {
+ AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
+ ApplicationReader applicationReader =
+ new ApplicationReader(androidApp, options, Timing.empty());
ExecutorService executorService = ThreadUtils.getExecutorService(options);
return applicationReader.read(executorService).toDirect();
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
deleted file mode 100644
index b415c354..0000000
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
-
-import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.utils.AndroidApiLevel;
-
-public class LibraryValidator {
-
- // Estimates if the library passed is at the expected minimum level, if it is not, raise
- // a warning.
- public static void validate(DexApplication app, AndroidApiLevel requiredCompilationAPILevel) {
- DexType levelType;
- if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.O)) {
- levelType = app.dexItemFactory.createType("Ljava/time/LocalTime;");
- } else if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.R)) {
- levelType = app.dexItemFactory.createType("Ljava/util/concurrent/Flow;");
- } else {
- app.options.reporter.warning(
- "Unsupported requiredCompilationAPILevel: " + requiredCompilationAPILevel);
- return;
- }
- DexClass dexClass = app.definitionFor(levelType);
- if (dexClass == null) {
- app.options.reporter.warning(
- "Desugared library requires to be compiled with a library file of API greater or equal to"
- + " "
- + requiredCompilationAPILevel
- + ", but it seems the library file passed is of a lower API.");
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index 33f7037..758812e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -24,10 +24,10 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
+import com.android.tools.r8.graph.LibraryMethod;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.BooleanUtils;
@@ -49,6 +49,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import org.objectweb.asm.Opcodes;
@@ -375,7 +376,12 @@
this.dexItemFactory = appView.dexItemFactory();
this.helper = new InterfaceDesugaringSyntheticHelper(appView);
needsLibraryInfo =
- appView.options().machineDesugaredLibrarySpecification.hasEmulatedInterfaces();
+ !appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface().isEmpty()
+ || !appView
+ .options()
+ .desugaredLibrarySpecification
+ .getRetargetCoreLibMember()
+ .isEmpty();
this.isLiveMethod = isLiveMethod;
}
@@ -504,7 +510,7 @@
DexClass iface = appView.definitionFor(emulatedInterface);
if (iface != null) {
assert iface.isLibraryClass()
- || appView.options().machineDesugaredLibrarySpecification.isLibraryCompilation();
+ || appView.options().desugaredLibrarySpecification.isLibraryCompilation();
workList.addIfNotSeen(iface.getInterfaces());
}
}
@@ -664,10 +670,10 @@
resolveForwardForSignature(
clazz,
wrapper.get(),
- (target, forward) -> {
+ target -> {
if (isLiveMethod(target) && !superInfo.isTargetedByForwards(target)) {
additionalForwards.add(target);
- addForwardingMethod(target, forward, clazz);
+ addForwardingMethod(target, clazz);
}
});
}
@@ -676,7 +682,7 @@
// Looks up a method signature from the point of 'clazz', if it can dispatch to a default method
// the 'addForward' call-back is called with the target of the forward.
private void resolveForwardForSignature(
- DexClass clazz, DexMethod method, BiConsumer<DexClassAndMethod, DexMethod> addForward) {
+ DexClass clazz, DexMethod method, Consumer<DexClassAndMethod> addForward) {
AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
MethodResolutionResult resolutionResult = appInfo.resolveMethodOn(clazz, method);
if (resolutionResult.isFailedResolution()
@@ -716,22 +722,50 @@
resolutionResult.lookupVirtualDispatchTarget(clazz, appInfo);
assert virtualDispatchTarget != null;
- // If resolution targets a default interface method, forward it.
- if (virtualDispatchTarget.isDefaultMethod()) {
- addForward.accept(
- virtualDispatchTarget,
- helper.ensureDefaultAsMethodOfCompanionClassStub(virtualDispatchTarget).getReference());
+ // Don't forward if the target is explicitly marked as 'dont-rewrite'
+ if (dontRewrite(virtualDispatchTarget)) {
return;
}
- DerivedMethod forwardingMethod =
- helper.computeEmulatedInterfaceForwardingMethod(
- virtualDispatchTarget.getHolder(), virtualDispatchTarget);
- if (forwardingMethod != null) {
- DexMethod concreteForwardingMethod =
- helper.ensureEmulatedInterfaceForwardingMethod(forwardingMethod);
- addForward.accept(virtualDispatchTarget, concreteForwardingMethod);
+ // If resolution targets a default interface method, forward it.
+ if (virtualDispatchTarget.isDefaultMethod()) {
+ addForward.accept(virtualDispatchTarget);
+ return;
}
+
+ // Remaining edge cases only pertain to desugaring of library methods.
+ if (!virtualDispatchTarget.isLibraryMethod() || ignoreLibraryInfo()) {
+ return;
+ }
+
+ LibraryMethod libraryMethod = virtualDispatchTarget.asLibraryMethod();
+ if (isRetargetMethod(libraryMethod)) {
+ addForward.accept(virtualDispatchTarget);
+ return;
+ }
+
+ // If target is a non-interface library class it may be an emulated interface,
+ // except on a rewritten type, where L8 has already dealt with the desugaring.
+ if (!libraryMethod.getHolder().isInterface()
+ && !appView.rewritePrefix.hasRewrittenType(libraryMethod.getHolderType(), appView)) {
+ // Here we use step-3 of resolution to find a maximally specific default interface method.
+ DexClassAndMethod result =
+ appInfo.lookupMaximallySpecificMethod(libraryMethod.getHolder(), method);
+ if (result != null && helper.isEmulatedInterface(result.getHolderType())) {
+ addForward.accept(result);
+ }
+ }
+ }
+
+ private boolean isRetargetMethod(LibraryMethod method) {
+ assert needsLibraryInfo();
+ assert method.getDefinition().isNonPrivateVirtualMethod();
+ return !method.getAccessFlags().isFinal()
+ && appView.options().desugaredLibrarySpecification.retargetMethod(method, appView) != null;
+ }
+
+ private boolean dontRewrite(DexClassAndMethod method) {
+ return needsLibraryInfo() && method.getHolder().isLibraryClass() && helper.dontRewrite(method);
}
// Construction of actual forwarding methods.
@@ -796,8 +830,7 @@
// Note: The parameter 'target' may be a public method on a class in case of desugared
// library retargeting (See below target.isInterface check).
- private void addForwardingMethod(
- DexClassAndMethod target, DexMethod forwardMethod, DexClass clazz) {
+ private void addForwardingMethod(DexClassAndMethod target, DexClass clazz) {
if (!clazz.isProgramClass()) {
return;
}
@@ -814,6 +847,10 @@
// NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
// even if this results in invalid code, these classes are never desugared.
// In desugared library, emulated interface methods can be overridden by retarget lib members.
+ DexMethod forwardMethod =
+ target.getHolder().isInterface()
+ ? helper.ensureDefaultAsMethodOfCompanionClassStub(target).getReference()
+ : appView.options().desugaredLibrarySpecification.retargetMethod(target, appView);
DexEncodedMethod desugaringForwardingMethod =
DexEncodedMethod.createDesugaringForwardingMethod(
target.getDefinition(), clazz, forwardMethod, dexItemFactory);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
index d06fee7..74d94e3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.utils.IterableUtils;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@@ -26,15 +25,8 @@
public EmulatedInterfaceApplicationRewriter(AppView<?> appView) {
this.appView = appView;
- emulatedInterfaces = new IdentityHashMap<>();
- appView
- .options()
- .machineDesugaredLibrarySpecification
- .getEmulatedInterfaces()
- .forEach(
- (ei, descriptor) -> {
- emulatedInterfaces.put(ei, descriptor.getRewrittenType());
- });
+ this.emulatedInterfaces =
+ appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface();
}
public void rewriteApplication(DexApplication.Builder<?> builder) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java
index 6636e1e..a3e0164 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java
@@ -4,12 +4,10 @@
package com.android.tools.r8.ir.desugar.itf;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-
public class InterfaceDesugaringForTesting {
public static String getEmulateLibraryClassNameSuffix() {
- return SyntheticKind.EMULATED_INTERFACE_CLASS.descriptor;
+ return InterfaceDesugaringSyntheticHelper.EMULATE_LIBRARY_CLASS_NAME_SUFFIX;
}
public static String getCompanionClassNameSuffix() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index cb4a537..77d99e5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -24,7 +24,6 @@
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.DexValue.DexValueInt;
@@ -32,20 +31,19 @@
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.InvalidCode;
import com.android.tools.r8.graph.MethodAccessFlags;
-import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ThrowNullCode;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedInterfaceDescriptor;
import com.android.tools.r8.ir.desugar.itf.EmulatedInterfaceSynthesizerEventConsumer.ClasspathEmulatedInterfaceSynthesizerEventConsumer;
import com.android.tools.r8.synthesis.SyntheticClassBuilder;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.ImmutableList;
+import java.util.Map;
+import java.util.Set;
import java.util.function.Predicate;
public class InterfaceDesugaringSyntheticHelper {
@@ -59,37 +57,37 @@
}
// Use InterfaceDesugaringForTesting for public accesses in tests.
+ static final String EMULATE_LIBRARY_CLASS_NAME_SUFFIX = "$-EL";
static final String COMPANION_CLASS_NAME_SUFFIX = "$-CC";
static final String DEFAULT_METHOD_PREFIX = "$default$";
static final String PRIVATE_METHOD_PREFIX = "$private$";
private final AppView<?> appView;
+ private final Map<DexType, DexType> emulatedInterfaces;
private final Predicate<DexType> shouldIgnoreFromReportsPredicate;
public InterfaceDesugaringSyntheticHelper(AppView<?> appView) {
this.appView = appView;
+ emulatedInterfaces =
+ appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface();
+
this.shouldIgnoreFromReportsPredicate = getShouldIgnoreFromReportsPredicate(appView);
}
boolean isEmulatedInterface(DexType itf) {
- return appView
- .options()
- .machineDesugaredLibrarySpecification
- .getEmulatedInterfaces()
- .containsKey(itf);
+ return emulatedInterfaces.containsKey(itf);
}
boolean isRewrittenEmulatedInterface(DexType itf) {
- return appView
- .options()
- .machineDesugaredLibrarySpecification
- .isEmulatedInterfaceRewrittenType(itf);
+ return emulatedInterfaces.containsValue(itf);
+ }
+
+ Set<DexType> getEmulatedInterfaces() {
+ return emulatedInterfaces.keySet();
}
DexType getEmulatedInterface(DexType type) {
- EmulatedInterfaceDescriptor interfaceDescriptor =
- appView.options().machineDesugaredLibrarySpecification.getEmulatedInterfaces().get(type);
- return interfaceDescriptor == null ? null : interfaceDescriptor.getRewrittenType();
+ return emulatedInterfaces.get(type);
}
boolean isInDesugaredLibrary(DexClass clazz) {
@@ -100,6 +98,17 @@
return appView.rewritePrefix.hasRewrittenType(clazz.type, appView);
}
+ boolean dontRewrite(DexClassAndMethod method) {
+ for (Pair<DexType, DexString> dontRewrite :
+ appView.options().desugaredLibrarySpecification.getDontRewriteInvocation()) {
+ if (method.getHolderType() == dontRewrite.getFirst()
+ && method.getName() == dontRewrite.getSecond()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
final boolean isCompatibleDefaultMethod(DexEncodedMethod method) {
assert !method.accessFlags.isConstructor();
assert !method.accessFlags.isStatic();
@@ -120,15 +129,25 @@
return true;
}
- DexMethod emulatedInterfaceDispatchMethod(DerivedMethod method, DexType holder) {
- assert method.getHolderKind() == SyntheticKind.EMULATED_INTERFACE_CLASS;
- DexProto newProto = appView.dexItemFactory().prependHolderToProto(method.getMethod());
- return appView.dexItemFactory().createMethod(holder, newProto, method.getName());
+ public DexMethod emulateInterfaceLibraryMethod(DexClassAndMethod method) {
+ DexItemFactory factory = appView.dexItemFactory();
+ return factory.createMethod(
+ getEmulateLibraryInterfaceClassType(method.getHolderType(), factory),
+ factory.prependTypeToProto(method.getHolderType(), method.getProto()),
+ method.getName());
}
- DexMethod emulatedInterfaceInterfaceMethod(DerivedMethod method) {
- assert method.getHolderKind() == null;
- return method.getMethod();
+ private static String getEmulateLibraryInterfaceClassDescriptor(String descriptor) {
+ return descriptor.substring(0, descriptor.length() - 1)
+ + EMULATE_LIBRARY_CLASS_NAME_SUFFIX
+ + ";";
+ }
+
+ public static DexType getEmulateLibraryInterfaceClassType(DexType type, DexItemFactory factory) {
+ assert type.isClassType();
+ String descriptor = type.descriptor.toString();
+ String elTypeDescriptor = getEmulateLibraryInterfaceClassDescriptor(descriptor);
+ return factory.createSynthesizedType(elTypeDescriptor);
}
public static String getCompanionClassDescriptor(String descriptor) {
@@ -148,6 +167,10 @@
return type.descriptor.toString().endsWith(COMPANION_CLASS_NAME_SUFFIX + ";");
}
+ public static boolean isEmulatedLibraryClassType(DexType type) {
+ return type.descriptor.toString().endsWith(EMULATE_LIBRARY_CLASS_NAME_SUFFIX + ";");
+ }
+
// Gets the interface class for a companion class `type`.
DexType getInterfaceClassType(DexType type) {
return getInterfaceClassType(type, appView.dexItemFactory());
@@ -174,91 +197,9 @@
SyntheticClassBuilder::setInterface);
}
- DexClassAndMethod lookupMaximallySpecificIncludingSelf(
- DexClass initialResolutionHolder, DexClassAndMethod method) {
- assert method.getHolderType().isClassType();
- if (method.getHolder().isInterface()) {
- return method;
- }
- return appView
- .appInfoForDesugaring()
- .lookupMaximallySpecificMethod(initialResolutionHolder, method.getReference());
- }
-
- EmulatedDispatchMethodDescriptor getEmulatedDispatchDescriptor(
- DexClass initialResolutionHolder, DexClassAndMethod method) {
- if (method == null) {
- return null;
- }
- assert initialResolutionHolder != null;
- // Outside L8 compilation, only library methods can lead to emulated interface dispatch.
- if (!method.isLibraryMethod() && !appView.options().isDesugaredLibraryCompilation()) {
- return null;
- }
- DexClassAndMethod maximallySpecificMethod =
- lookupMaximallySpecificIncludingSelf(initialResolutionHolder, method);
- if (maximallySpecificMethod == null) {
- return null;
- }
- EmulatedDispatchMethodDescriptor descriptor =
- appView
- .options()
- .machineDesugaredLibrarySpecification
- .getEmulatedInterfaceEmulatedDispatchMethodDescriptor(
- maximallySpecificMethod.getReference());
- if (!appView.options().isDesugaredLibraryCompilation()) {
- return descriptor;
- }
- return requiresEmulatedDispatchInL8(method, descriptor) ? descriptor : null;
- }
-
- private boolean requiresEmulatedDispatchInL8(
- DexClassAndMethod method, EmulatedDispatchMethodDescriptor descriptor) {
- return method.isLibraryMethod()
- || isEmulatedInterface(method.getHolderType())
- || (descriptor != null
- && descriptor.getDispatchCases().containsKey(method.getHolderType()));
- }
-
- DerivedMethod computeEmulatedInterfaceDispatchMethod(MethodResolutionResult resolutionResult) {
- EmulatedDispatchMethodDescriptor descriptor =
- getEmulatedDispatchDescriptor(
- resolutionResult.getInitialResolutionHolder(), resolutionResult.getResolutionPair());
- return descriptor == null ? null : descriptor.getEmulatedDispatchMethod();
- }
-
- DerivedMethod computeEmulatedInterfaceForwardingMethod(
- DexClass initialResolutionHolder, DexClassAndMethod method) {
- EmulatedDispatchMethodDescriptor descriptor =
- getEmulatedDispatchDescriptor(initialResolutionHolder, method);
- if (descriptor == null) {
- return null;
- }
- return descriptor.getDispatchCases().containsKey(method.getHolderType())
- ? descriptor.getDispatchCases().get(method.getHolderType())
- : descriptor.getForwardingMethod();
- }
-
- DexMethod ensureEmulatedInterfaceForwardingMethod(DerivedMethod method) {
- if (method.getHolderKind() == null) {
- return method.getMethod();
- }
- assert method.getHolderKind() == SyntheticKind.COMPANION_CLASS;
- DexClassAndMethod resolvedMethod =
- appView.appInfoForDesugaring().resolveMethod(method.getMethod(), true).getResolutionPair();
- return ensureDefaultAsMethodOfCompanionClassStub(resolvedMethod).getReference();
- }
-
- DexClassAndMethod ensureEmulatedInterfaceDispatchMethod(
- DerivedMethod emulatedDispatchMethod,
- ClasspathEmulatedInterfaceSynthesizerEventConsumer eventConsumer) {
- assert emulatedDispatchMethod.getHolderKind() == SyntheticKind.EMULATED_INTERFACE_CLASS;
- DexClassAndMethod method =
- appView
- .appInfoForDesugaring()
- .resolveMethod(emulatedDispatchMethod.getMethod(), true)
- .getResolutionPair();
- assert emulatedDispatchMethod.getHolderKind() == SyntheticKind.EMULATED_INTERFACE_CLASS;
+ DexClassAndMethod ensureEmulatedInterfaceMethod(
+ DexClassAndMethod method, ClasspathEmulatedInterfaceSynthesizerEventConsumer eventConsumer) {
+ DexMethod emulatedInterfaceMethod = emulateInterfaceLibraryMethod(method);
if (method.isProgramMethod()) {
assert appView.options().isDesugaredLibraryCompilation();
DexProgramClass emulatedInterface =
@@ -268,15 +209,8 @@
SyntheticKind.EMULATED_INTERFACE_CLASS,
method.asProgramMethod().getHolder(),
appView);
- DexMethod emulatedInterfaceMethod =
- emulatedInterfaceDispatchMethod(emulatedDispatchMethod, emulatedInterface.type);
- assert emulatedInterface.lookupProgramMethod(emulatedInterfaceMethod) != null;
return emulatedInterface.lookupProgramMethod(emulatedInterfaceMethod);
}
- // The holder is not used.
- DexMethod emulatedInterfaceMethod =
- emulatedInterfaceDispatchMethod(
- emulatedDispatchMethod, appView.dexItemFactory().objectType);
return appView
.getSyntheticItems()
.ensureFixedClasspathClassMethod(
@@ -577,7 +511,7 @@
return appView.rewritePrefix.hasRewrittenType(type, appView)
|| descriptor.endsWith(companionClassNameDescriptorSuffix)
|| isRewrittenEmulatedInterface(type)
- || options.machineDesugaredLibrarySpecification.isCustomConversionRewrittenType(type)
+ || options.desugaredLibrarySpecification.getCustomConversions().containsValue(type)
|| appView.getDontWarnConfiguration().matches(type);
};
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 0227b1f..6740441 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -35,8 +35,7 @@
import com.android.tools.r8.ir.desugar.DesugarDescription;
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.icce.AlwaysThrowingInstructionDesugaring;
import com.android.tools.r8.ir.desugar.lambda.LambdaInstructionDesugaring;
import com.android.tools.r8.ir.desugar.stringconcat.StringConcatInstructionDesugaring;
@@ -54,6 +53,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
import java.util.function.Predicate;
//
@@ -119,31 +119,18 @@
}
public static void checkForAssumedLibraryTypes(AppInfo appInfo, InternalOptions options) {
- MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification =
- options.machineDesugaredLibrarySpecification;
- machineDesugaredLibrarySpecification
- .getEmulatedInterfaces()
- .forEach(
- (ei, descriptor) -> {
- registerType(appInfo, ei);
- registerType(appInfo, descriptor.getRewrittenType());
- descriptor
- .getEmulatedMethods()
- .forEach(
- (method, methodDescriptor) -> {
- methodDescriptor
- .getDispatchCases()
- .keySet()
- .forEach(t -> registerType(appInfo, t));
- });
- });
- machineDesugaredLibrarySpecification
- .getCustomConversions()
- .forEach(
- (type, conversionPair) -> {
- registerType(appInfo, type);
- registerType(appInfo, conversionPair.getFirst());
- });
+ LegacyDesugaredLibrarySpecification spec = options.desugaredLibrarySpecification;
+ BiConsumer<DexType, DexType> registerEntry = registerMapEntry(appInfo);
+ spec.getEmulateLibraryInterface().forEach(registerEntry);
+ spec.getCustomConversions().forEach(registerEntry);
+ spec.getRetargetCoreLibMember().forEach((method, types) -> types.forEach(registerEntry));
+ }
+
+ private static BiConsumer<DexType, DexType> registerMapEntry(AppInfo appInfo) {
+ return (key, value) -> {
+ registerType(appInfo, key);
+ registerType(appInfo, value);
+ };
}
private static void registerType(AppInfo appInfo, DexType type) {
@@ -169,9 +156,9 @@
}
private void initializeEmulatedInterfaceVariables() {
- Set<DexType> emulateLibraryInterface =
- options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().keySet();
- for (DexType interfaceType : emulateLibraryInterface) {
+ Map<DexType, DexType> emulateLibraryInterface =
+ options.desugaredLibrarySpecification.getEmulateLibraryInterface();
+ for (DexType interfaceType : emulateLibraryInterface.keySet()) {
DexClass emulatedInterfaceClass = appView.definitionFor(interfaceType);
if (emulatedInterfaceClass != null) {
for (DexEncodedMethod encodedMethod :
@@ -462,27 +449,24 @@
}
private DesugarDescription computeEmulatedInterfaceVirtualDispatchOrNull(CfInvoke invoke) {
- MethodResolutionResult resolutionResult =
- appView.appInfoForDesugaring().resolveMethod(invoke.getMethod(), invoke.isInterface());
- DerivedMethod emulatedDispatchMethod =
- helper.computeEmulatedInterfaceDispatchMethod(resolutionResult);
- if (emulatedDispatchMethod == null) {
- return null;
+ DexClassAndMethod defaultMethod =
+ defaultMethodForEmulatedDispatchOrNull(invoke.getMethod(), invoke.isInterface());
+ if (defaultMethod != null) {
+ return DesugarDescription.builder()
+ .setDesugarRewrite(
+ (freshLocalProvider,
+ localStackAllocator,
+ eventConsumer,
+ context1,
+ methodProcessingContext,
+ dexItemFactory) ->
+ getInvokeStaticInstructions(
+ helper
+ .ensureEmulatedInterfaceMethod(defaultMethod, eventConsumer)
+ .getReference()))
+ .build();
}
- return DesugarDescription.builder()
- .setDesugarRewrite(
- (freshLocalProvider,
- localStackAllocator,
- eventConsumer,
- context1,
- methodProcessingContext,
- dexItemFactory) ->
- getInvokeStaticInstructions(
- helper
- .ensureEmulatedInterfaceDispatchMethod(
- emulatedDispatchMethod, eventConsumer)
- .getReference()))
- .build();
+ return null;
}
private DesugarDescription computeInvokeDirect(
@@ -720,49 +704,103 @@
private DesugarDescription computeEmulatedInterfaceInvokeSpecial(
DexClass clazz, DexMethod invokedMethod, ProgramMethod context) {
- DexClassAndMethod superTarget =
- appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, context);
- if (clazz.isInterface() && appView.rewritePrefix.hasRewrittenType(clazz.type, appView)) {
- if (superTarget != null && superTarget.getDefinition().isDefaultMethod()) {
- DexClass holder = superTarget.getHolder();
- if (holder.isLibraryClass() && holder.isInterface()) {
- return DesugarDescription.builder()
- .setDesugarRewrite(
- (freshLocalProvider,
- localStackAllocator,
- eventConsumer,
- context13,
- methodProcessingContext,
- dexItemFactory) -> {
- DexClassAndMethod companionTarget =
- helper.ensureDefaultAsMethodOfCompanionClassStub(superTarget);
- acceptCompanionMethod(superTarget, companionTarget, eventConsumer);
- return getInvokeStaticInstructions(companionTarget.getReference());
- })
- .build();
+ DexType emulatedItf = maximallySpecificEmulatedInterfaceOrNull(invokedMethod);
+ if (emulatedItf == null) {
+ if (clazz.isInterface() && appView.rewritePrefix.hasRewrittenType(clazz.type, appView)) {
+ DexClassAndMethod target =
+ appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, context);
+ if (target != null && target.getDefinition().isDefaultMethod()) {
+ DexClass holder = target.getHolder();
+ if (holder.isLibraryClass() && holder.isInterface()) {
+ return DesugarDescription.builder()
+ .setDesugarRewrite(
+ (freshLocalProvider,
+ localStackAllocator,
+ eventConsumer,
+ context13,
+ methodProcessingContext,
+ dexItemFactory) -> {
+ DexClassAndMethod companionTarget =
+ helper.ensureDefaultAsMethodOfCompanionClassStub(target);
+ acceptCompanionMethod(target, companionTarget, eventConsumer);
+ return getInvokeStaticInstructions(companionTarget.getReference());
+ })
+ .build();
+ }
}
}
+ return DesugarDescription.nothing();
}
// That invoke super may not resolve since the super method may not be present
// since it's in the emulated interface. We need to force resolution. If it resolves
// to a library method, then it needs to be rewritten.
// If it resolves to a program overrides, the invoke-super can remain.
- DerivedMethod forwardingMethod =
- helper.computeEmulatedInterfaceForwardingMethod(clazz, superTarget);
- if (forwardingMethod == null) {
- return DesugarDescription.nothing();
+ DexClassAndMethod superTarget =
+ appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, context);
+ if (superTarget != null && superTarget.isLibraryMethod()) {
+ // Rewriting is required because the super invoke resolves into a missing
+ // method (method is on desugared library). Find out if it needs to be
+ // retargeted or if it just calls a companion class method and rewrite.
+ DexMethod retargetMethod =
+ options.desugaredLibrarySpecification.retargetMethod(superTarget, appView);
+ if (retargetMethod != null) {
+ return DesugarDescription.builder()
+ .setDesugarRewrite(
+ (freshLocalProvider,
+ localStackAllocator,
+ eventConsumer,
+ context14,
+ methodProcessingContext,
+ dexItemFactory) -> getInvokeStaticInstructions(retargetMethod))
+ .build();
+ }
+ DexClassAndMethod emulatedMethod =
+ superTarget.getReference().lookupMemberOnClass(appView.definitionFor(emulatedItf));
+ if (emulatedMethod == null) {
+ assert false;
+ return DesugarDescription.nothing();
+ }
+ return DesugarDescription.builder()
+ .setDesugarRewrite(
+ (freshLocalProvider,
+ localStackAllocator,
+ eventConsumer,
+ context15,
+ methodProcessingContext,
+ dexItemFactory) -> {
+ DexClassAndMethod companionMethod =
+ helper.ensureDefaultAsMethodOfCompanionClassStub(emulatedMethod);
+ return getInvokeStaticInstructions(companionMethod.getReference());
+ })
+ .build();
}
- return DesugarDescription.builder()
- .setDesugarRewrite(
- (freshLocalProvider,
- localStackAllocator,
- eventConsumer,
- context14,
- methodProcessingContext,
- dexItemFactory) ->
- getInvokeStaticInstructions(
- helper.ensureEmulatedInterfaceForwardingMethod(forwardingMethod)))
- .build();
+ return DesugarDescription.nothing();
+ }
+
+ private DexClassAndMethod defaultMethodForEmulatedDispatchOrNull(
+ DexMethod invokedMethod, boolean interfaceBit) {
+ DexType emulatedItf = maximallySpecificEmulatedInterfaceOrNull(invokedMethod);
+ if (emulatedItf == null) {
+ return null;
+ }
+ // The call potentially ends up in a library class, in which case we need to rewrite, since the
+ // code may be in the desugared library.
+ SingleResolutionResult resolution =
+ appView
+ .appInfoForDesugaring()
+ .resolveMethod(invokedMethod, interfaceBit)
+ .asSingleResolution();
+ if (resolution != null
+ && (resolution.getResolvedHolder().isLibraryClass()
+ || helper.isEmulatedInterface(resolution.getResolvedHolder().type))) {
+ DexClassAndMethod defaultMethod =
+ appView.definitionFor(emulatedItf).lookupClassMethod(invokedMethod);
+ if (defaultMethod != null && !helper.dontRewrite(defaultMethod)) {
+ assert !defaultMethod.getAccessFlags().isAbstract();
+ return defaultMethod;
+ }
+ }
+ return null;
}
private boolean shouldRewriteToInvokeToThrow(
@@ -771,6 +809,40 @@
|| resolutionResult.getResolvedMethod().isStatic() != isInvokeStatic;
}
+ private DexType maximallySpecificEmulatedInterfaceOrNull(DexMethod invokedMethod) {
+ // Here we try to avoid doing the expensive look-up on all invokes.
+ if (!emulatedMethods.contains(invokedMethod.name)) {
+ return null;
+ }
+ DexClass dexClass = appView.definitionFor(invokedMethod.holder);
+ // We cannot rewrite the invoke we do not know what the class is.
+ if (dexClass == null) {
+ return null;
+ }
+ DexEncodedMethod singleTarget = null;
+ if (dexClass.isInterface()) {
+ // Look for exact method on the interface.
+ singleTarget = dexClass.lookupMethod(invokedMethod);
+ }
+ if (singleTarget == null) {
+ DexClassAndMethod result =
+ appView.appInfoForDesugaring().lookupMaximallySpecificMethod(dexClass, invokedMethod);
+ if (result != null) {
+ singleTarget = result.getDefinition();
+ }
+ }
+ if (singleTarget == null) {
+ // At this point we are in a library class. Failures can happen with NoSuchMethod if a
+ // library class implement a method with same signature but not related to emulated
+ // interfaces.
+ return null;
+ }
+ if (!singleTarget.isAbstract() && helper.isEmulatedInterface(singleTarget.getHolderType())) {
+ return singleTarget.getHolderType();
+ }
+ return null;
+ }
+
private boolean isNonDesugaredLibraryClass(DexClass clazz) {
return clazz.isLibraryClass() && !helper.isInDesugaredLibrary(clazz);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
index 7e8a2cc..f712cb4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
@@ -5,9 +5,11 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedMethod;
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.MethodAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
@@ -23,16 +25,27 @@
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.synthesis.SyntheticProgramClassBuilder;
import com.android.tools.r8.utils.StringDiagnostic;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public final class ProgramEmulatedInterfaceSynthesizer implements CfClassSynthesizerDesugaring {
private final AppView<?> appView;
private final InterfaceDesugaringSyntheticHelper helper;
+ private final Map<DexType, List<DexType>> emulatedInterfacesHierarchy;
public static ProgramEmulatedInterfaceSynthesizer create(AppView<?> appView) {
if (!appView.options().isDesugaredLibraryCompilation()
- || !appView.options().machineDesugaredLibrarySpecification.hasEmulatedInterfaces()) {
+ || appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface().isEmpty()) {
return null;
}
return new ProgramEmulatedInterfaceSynthesizer(appView);
@@ -41,11 +54,53 @@
public ProgramEmulatedInterfaceSynthesizer(AppView<?> appView) {
this.appView = appView;
helper = new InterfaceDesugaringSyntheticHelper(appView);
+ // Avoid the computation outside L8 since it is not needed.
+ emulatedInterfacesHierarchy =
+ appView.options().isDesugaredLibraryCompilation()
+ ? processEmulatedInterfaceHierarchy()
+ : Collections.emptyMap();
+ }
+
+ private Map<DexType, List<DexType>> processEmulatedInterfaceHierarchy() {
+ Map<DexType, List<DexType>> emulatedInterfacesHierarchy = new IdentityHashMap<>();
+ Set<DexType> processed = Sets.newIdentityHashSet();
+ ArrayList<DexType> emulatedInterfacesSorted = new ArrayList<>(helper.getEmulatedInterfaces());
+ emulatedInterfacesSorted.sort(DexType::compareTo);
+ for (DexType interfaceType : emulatedInterfacesSorted) {
+ processEmulatedInterfaceHierarchy(interfaceType, processed, emulatedInterfacesHierarchy);
+ }
+ return emulatedInterfacesHierarchy;
+ }
+
+ private void processEmulatedInterfaceHierarchy(
+ DexType interfaceType,
+ Set<DexType> processed,
+ Map<DexType, List<DexType>> emulatedInterfacesHierarchy) {
+ if (processed.contains(interfaceType)) {
+ return;
+ }
+ emulatedInterfacesHierarchy.put(interfaceType, new ArrayList<>());
+ processed.add(interfaceType);
+ DexClass theInterface = appView.definitionFor(interfaceType);
+ if (theInterface == null) {
+ return;
+ }
+ LinkedList<DexType> workList = new LinkedList<>(Arrays.asList(theInterface.interfaces.values));
+ while (!workList.isEmpty()) {
+ DexType next = workList.removeLast();
+ if (helper.isEmulatedInterface(next)) {
+ processEmulatedInterfaceHierarchy(next, processed, emulatedInterfacesHierarchy);
+ emulatedInterfacesHierarchy.get(next).add(interfaceType);
+ DexClass nextClass = appView.definitionFor(next);
+ if (nextClass != null) {
+ workList.addAll(Arrays.asList(nextClass.interfaces.values));
+ }
+ }
+ }
}
DexProgramClass synthesizeProgramEmulatedInterface(
DexProgramClass emulatedInterface,
- EmulatedInterfaceDescriptor emulatedInterfaceDescriptor,
L8ProgramEmulatedInterfaceSynthesizerEventConsumer eventConsumer) {
return appView
.getSyntheticItems()
@@ -53,26 +108,20 @@
SyntheticNaming.SyntheticKind.EMULATED_INTERFACE_CLASS,
emulatedInterface,
appView,
- builder ->
- synthesizeEmulateInterfaceMethods(
- emulatedInterface, emulatedInterfaceDescriptor, builder),
+ builder -> synthesizeEmulateInterfaceMethods(emulatedInterface, builder),
eventConsumer::acceptProgramEmulatedInterface);
}
private void synthesizeEmulateInterfaceMethods(
- DexProgramClass emulatedInterface,
- EmulatedInterfaceDescriptor emulatedInterfaceDescriptor,
- SyntheticProgramClassBuilder builder) {
+ DexProgramClass emulatedInterface, SyntheticProgramClassBuilder builder) {
+ assert helper.isEmulatedInterface(emulatedInterface.type);
emulatedInterface.forEachProgramVirtualMethodMatching(
- m -> emulatedInterfaceDescriptor.getEmulatedMethods().containsKey(m.getReference()),
+ DexEncodedMethod::isDefaultMethod,
method ->
builder.addMethod(
methodBuilder ->
synthesizeEmulatedInterfaceMethod(
- method,
- emulatedInterfaceDescriptor.getEmulatedMethods().get(method.getReference()),
- builder.getType(),
- methodBuilder)));
+ method, emulatedInterface, builder.getType(), methodBuilder)));
}
private DexMethod emulatedMethod(DerivedMethod method, DexType holder) {
@@ -88,17 +137,24 @@
private void synthesizeEmulatedInterfaceMethod(
ProgramMethod method,
- EmulatedDispatchMethodDescriptor descriptor,
+ DexProgramClass theInterface,
DexType dispatchType,
SyntheticMethodBuilder methodBuilder) {
assert !method.getDefinition().isStatic();
- DexMethod emulatedMethod =
- helper.emulatedInterfaceDispatchMethod(
- descriptor.getEmulatedDispatchMethod(), dispatchType);
- DexMethod itfMethod = helper.emulatedInterfaceInterfaceMethod(descriptor.getInterfaceMethod());
+ if (appView.options().testing.machineDesugaredLibrarySpecification != null) {
+ synthesizeEmulatedInterfaceMethodFromMachineSpecification(
+ method, theInterface, dispatchType, methodBuilder);
+ return;
+ }
+ DexMethod emulatedMethod = helper.emulateInterfaceLibraryMethod(method);
+ DexMethod itfMethod =
+ method
+ .getReference()
+ .withHolder(helper.getEmulatedInterface(theInterface.type), appView.dexItemFactory());
DexMethod companionMethod =
- helper.ensureEmulatedInterfaceForwardingMethod(descriptor.getForwardingMethod());
- LinkedHashMap<DexType, DexMethod> extraDispatchCases = resolveDispatchCases(descriptor);
+ helper.ensureDefaultAsMethodOfProgramCompanionClassStub(method).getReference();
+ LinkedHashMap<DexType, DexMethod> extraDispatchCases =
+ getDispatchCases(method, theInterface, companionMethod);
methodBuilder
.setName(emulatedMethod.getName())
.setProto(emulatedMethod.getProto())
@@ -114,40 +170,162 @@
.generateCfCode());
}
+ private void synthesizeEmulatedInterfaceMethodFromMachineSpecification(
+ ProgramMethod method,
+ DexProgramClass theInterface,
+ DexType dispatchType,
+ SyntheticMethodBuilder methodBuilder) {
+ EmulatedInterfaceDescriptor emulatedInterfaceDescriptor =
+ appView
+ .options()
+ .testing
+ .machineDesugaredLibrarySpecification
+ .getRewritingFlags()
+ .getEmulatedInterfaces()
+ .get(theInterface.type);
+ EmulatedDispatchMethodDescriptor descriptor =
+ emulatedInterfaceDescriptor.getEmulatedMethods().get(method.getReference());
+ DexMethod emulatedMethod = emulatedMethod(descriptor.getEmulatedDispatchMethod(), dispatchType);
+ DexMethod itfMethod = interfaceMethod(descriptor.getInterfaceMethod());
+ // TODO(b/184026720): Adapt to use the forwarding method.
+ DerivedMethod forwardingMethod = descriptor.getForwardingMethod();
+ assert forwardingMethod.getHolderKind() == SyntheticKind.COMPANION_CLASS;
+ assert forwardingMethod.getMethod() == method.getReference();
+ DexMethod companionMethod =
+ helper.ensureDefaultAsMethodOfProgramCompanionClassStub(method).getReference();
+ LinkedHashMap<DexType, DexMethod> extraDispatchCases = resolveDispatchCases(descriptor);
+ methodBuilder
+ .setName(descriptor.getEmulatedDispatchMethod().getName())
+ .setProto(descriptor.getEmulatedDispatchMethod().getProto())
+ .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
+ .setCode(
+ emulatedInterfaceMethod ->
+ new EmulateDispatchSyntheticCfCodeProvider(
+ emulatedMethod.getHolderType(),
+ companionMethod,
+ itfMethod,
+ extraDispatchCases,
+ appView)
+ .generateCfCode());
+ }
+
private LinkedHashMap<DexType, DexMethod> resolveDispatchCases(
EmulatedDispatchMethodDescriptor descriptor) {
LinkedHashMap<DexType, DexMethod> extraDispatchCases = new LinkedHashMap<>();
descriptor
.getDispatchCases()
.forEach(
- (type, derivedMethod) ->
- extraDispatchCases.put(
- type, helper.ensureEmulatedInterfaceForwardingMethod(derivedMethod)));
+ (type, derivedMethod) -> {
+ DexMethod caseMethod;
+ if (derivedMethod.getHolderKind() == null) {
+ caseMethod = derivedMethod.getMethod();
+ } else {
+ assert derivedMethod.getHolderKind() == SyntheticKind.COMPANION_CLASS;
+ ProgramMethod resolvedProgramMethod =
+ appView
+ .appInfoForDesugaring()
+ .resolveMethod(derivedMethod.getMethod(), true)
+ .getResolvedProgramMethod();
+ caseMethod =
+ helper
+ .ensureDefaultAsMethodOfProgramCompanionClassStub(resolvedProgramMethod)
+ .getReference();
+ }
+ extraDispatchCases.put(type, caseMethod);
+ });
return extraDispatchCases;
}
+ private LinkedHashMap<DexType, DexMethod> getDispatchCases(
+ ProgramMethod method, DexProgramClass theInterface, DexMethod companionMethod) {
+ // To properly emulate the library interface call, we need to compute the interfaces
+ // inheriting from the interface and manually implement the dispatch with instance of.
+ // The list guarantees that an interface is always after interfaces it extends,
+ // hence reverse iteration.
+ List<DexType> subInterfaces = emulatedInterfacesHierarchy.get(theInterface.type);
+ LinkedHashMap<DexType, DexMethod> extraDispatchCases = new LinkedHashMap<>();
+ // In practice, there is usually a single case (except for tests),
+ // so we do not bother to make the following loop more clever.
+ Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+ appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember();
+ for (DexString methodName : retargetCoreLibMember.keySet()) {
+ if (method.getName() == methodName) {
+ for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+ DexClass inClass = appView.definitionFor(inType);
+ if (inClass != null && implementsInterface(inClass, theInterface.type)) {
+ extraDispatchCases.put(
+ inType,
+ appView
+ .dexItemFactory()
+ .createMethod(
+ retargetCoreLibMember.get(methodName).get(inType),
+ appView
+ .dexItemFactory()
+ .protoWithDifferentFirstParameter(companionMethod.proto, inType),
+ method.getName()));
+ }
+ }
+ }
+ }
+ if (subInterfaces != null) {
+ for (int i = subInterfaces.size() - 1; i >= 0; i--) {
+ DexClass subInterfaceClass = appView.definitionFor(subInterfaces.get(i));
+ assert subInterfaceClass != null;
+ assert subInterfaceClass.isProgramClass();
+ // Else computation of subInterface would have failed.
+ // if the method is implemented, extra dispatch is required.
+ DexEncodedMethod result = subInterfaceClass.lookupVirtualMethod(method.getReference());
+ if (result != null && !result.isAbstract()) {
+ assert result.isDefaultMethod();
+ DexMethod forward =
+ helper
+ .ensureDefaultAsMethodOfProgramCompanionClassStub(
+ new ProgramMethod(subInterfaceClass.asProgramClass(), result))
+ .getReference();
+ extraDispatchCases.put(subInterfaceClass.type, forward);
+ }
+ }
+ } else {
+ assert extraDispatchCases.size() <= 1;
+ }
+ return extraDispatchCases;
+ }
+
+ private boolean implementsInterface(DexClass clazz, DexType interfaceType) {
+ LinkedList<DexType> workList = new LinkedList<>(Arrays.asList(clazz.interfaces.values));
+ while (!workList.isEmpty()) {
+ DexType next = workList.removeLast();
+ if (interfaceType == next) {
+ return true;
+ }
+ DexClass nextClass = appView.definitionFor(next);
+ if (nextClass != null) {
+ workList.addAll(Arrays.asList(nextClass.interfaces.values));
+ }
+ }
+ return false;
+ }
+
@Override
public void synthesizeClasses(CfClassSynthesizerDesugaringEventConsumer eventConsumer) {
assert appView.options().isDesugaredLibraryCompilation();
- appView
- .options()
- .machineDesugaredLibrarySpecification
- .getEmulatedInterfaces()
- .forEach(
- (emulatedInterfaceType, emulatedInterfaceDescriptor) -> {
- DexClass emulatedInterfaceClazz = appView.definitionFor(emulatedInterfaceType);
- if (emulatedInterfaceClazz == null || !emulatedInterfaceClazz.isProgramClass()) {
- warnMissingEmulatedInterface(emulatedInterfaceType);
- return;
- }
- DexProgramClass emulatedInterface = emulatedInterfaceClazz.asProgramClass();
- assert emulatedInterface != null;
- if (!appView.isAlreadyLibraryDesugared(emulatedInterface)
- && !emulatedInterfaceDescriptor.getEmulatedMethods().isEmpty()) {
- synthesizeProgramEmulatedInterface(
- emulatedInterface, emulatedInterfaceDescriptor, eventConsumer);
- }
- });
+ for (DexType emulatedInterfaceType : helper.getEmulatedInterfaces()) {
+ DexClass emulatedInterfaceClazz = appView.definitionFor(emulatedInterfaceType);
+ if (emulatedInterfaceClazz == null || !emulatedInterfaceClazz.isProgramClass()) {
+ warnMissingEmulatedInterface(emulatedInterfaceType);
+ continue;
+ }
+ DexProgramClass emulatedInterface = emulatedInterfaceClazz.asProgramClass();
+ assert emulatedInterface != null;
+ if (!appView.isAlreadyLibraryDesugared(emulatedInterface)
+ && needsEmulateInterfaceLibrary(emulatedInterface)) {
+ synthesizeProgramEmulatedInterface(emulatedInterface, eventConsumer);
+ }
+ }
+ }
+
+ private boolean needsEmulateInterfaceLibrary(DexClass emulatedInterface) {
+ return Iterables.any(emulatedInterface.methods(), DexEncodedMethod::isDefaultMethod);
}
private void warnMissingEmulatedInterface(DexType interfaceType) {
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 0c1e782..e156407 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -665,6 +665,7 @@
|| getMissingClasses().contains(type)
// TODO(b/150693139): Remove these exceptions once fixed.
|| InterfaceDesugaringSyntheticHelper.isCompanionClassType(type)
+ || InterfaceDesugaringSyntheticHelper.isEmulatedLibraryClassType(type)
// TODO(b/150736225): Not sure how to remove these.
|| DesugaredLibraryAPIConverter.isVivifiedType(type)
: "Failed lookup of non-missing type: " + type;
diff --git a/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java b/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
index ab0a04d..960ccd5 100644
--- a/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
@@ -28,9 +28,9 @@
public L8TreePruner(InternalOptions options) {
this.options = options;
- backports.addAll(options.machineDesugaredLibrarySpecification.getLegacyBackport().keySet());
+ backports.addAll(options.desugaredLibrarySpecification.getBackportCoreLibraryMember().keySet());
emulatedInterfaces.addAll(
- options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().keySet());
+ options.desugaredLibrarySpecification.getEmulateLibraryInterface().keySet());
}
public DexApplication prune(DexApplication app, PrefixRewritingMapper rewritePrefix) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index 604748a..bbf4258 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -129,7 +129,12 @@
return;
}
assert hygienicType.toSourceString().startsWith(synthesizingContextType.toSourceString());
- DexType rewrittenContext = appView.rewritePrefix.rewrittenContextType(synthesizingContextType);
+ DexType rewrittenContext =
+ appView
+ .options()
+ .desugaredLibrarySpecification
+ .getEmulateLibraryInterface()
+ .get(synthesizingContextType);
if (rewrittenContext == null) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index 6d45ee1..0cb0137 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -483,7 +483,8 @@
AppView<?> appView,
DexType type) {
DexType rewrittenContextType =
- appView.rewritePrefix.rewrittenContextType(outerContext.getSynthesizingContextType());
+ appView.rewritePrefix.rewrittenContextType(
+ outerContext.getSynthesizingContextType(), appView);
if (rewrittenContextType == null) {
return;
}
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 467ac25..ec5dca6 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -54,11 +54,8 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.MachineDesugarPrefixRewritingMapper;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LegacyToHumanSpecificationConverter;
import com.android.tools.r8.ir.desugar.nest.Nest;
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.ir.optimize.enums.EnumDataMap;
@@ -88,9 +85,7 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
-import java.io.IOException;
import java.io.PrintStream;
-import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -395,8 +390,8 @@
if (isGeneratingDex() || desugarState == DesugarState.ON) {
marker.setMinApi(getMinApiLevel().getLevel());
}
- if (machineDesugaredLibrarySpecification.getIdentifier() != null) {
- marker.setDesugaredLibraryIdentifiers(machineDesugaredLibrarySpecification.getIdentifier());
+ if (desugaredLibrarySpecification.getIdentifier() != null) {
+ marker.setDesugaredLibraryIdentifiers(desugaredLibrarySpecification.getIdentifier());
}
if (Version.isDevelopmentVersion()) {
marker.setSha1(VersionProperties.INSTANCE.getSha());
@@ -443,7 +438,7 @@
}
public boolean isDesugaredLibraryCompilation() {
- return machineDesugaredLibrarySpecification.isLibraryCompilation();
+ return desugaredLibrarySpecification.isLibraryCompilation();
}
public boolean isRelocatorCompilation() {
@@ -893,51 +888,13 @@
public LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
LegacyDesugaredLibrarySpecification.empty();
- public void setDesugaredLibrarySpecification(
- LegacyDesugaredLibrarySpecification specification, AndroidApp app) {
- if (specification.isEmptyConfiguration()) {
- return;
- }
- desugaredLibrarySpecification = specification;
- try {
- HumanDesugaredLibrarySpecification human =
- new LegacyToHumanSpecificationConverter()
- .convert(specification, app.getLibraryResourceProviders(), this);
- machineDesugaredLibrarySpecification =
- new HumanToMachineSpecificationConverter()
- .convert(
- human,
- specification.isLibraryCompilation() ? app.getProgramResourceProviders() : null,
- app.getLibraryResourceProviders(),
- this);
- } catch (IOException e) {
- reporter.error(new ExceptionDiagnostic(e, Origin.unknown()));
- }
- }
-
- public void setDesugaredLibrarySpecificationForTesting(
- LegacyDesugaredLibrarySpecification specification, Path desugaredJDKLib, Path library)
- throws IOException {
- desugaredLibrarySpecification = specification;
- HumanDesugaredLibrarySpecification human =
- new LegacyToHumanSpecificationConverter().convert(specification, library, this);
- machineDesugaredLibrarySpecification =
- new HumanToMachineSpecificationConverter()
- .convert(
- human,
- specification.isLibraryCompilation() ? desugaredJDKLib : null,
- library,
- this);
- }
-
- // Meant to replace desugaredLibrarySpecification, set only from tests at the moment.
- public MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification =
- MachineDesugaredLibrarySpecification.empty();
-
public PrefixRewritingMapper getPrefixRewritingMapper() {
- return machineDesugaredLibrarySpecification.getRewriteType().isEmpty()
- ? PrefixRewritingMapper.empty()
- : new MachineDesugarPrefixRewritingMapper(machineDesugaredLibrarySpecification);
+ if (testing.machineDesugaredLibrarySpecification != null) {
+ return new MachineDesugarPrefixRewritingMapper(
+ desugaredLibrarySpecification.getPrefixRewritingMapper(),
+ testing.machineDesugaredLibrarySpecification.getRewritingFlags());
+ }
+ return desugaredLibrarySpecification.getPrefixRewritingMapper();
}
public boolean relocatorCompilation = false;
@@ -1642,6 +1599,9 @@
public Consumer<Deque<ProgramMethodSet>> waveModifier = waves -> {};
+ // Meant to replace desugaredLibrarySpecification, set only from tests at the moment.
+ public MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification = null;
+
/**
* If this flag is enabled, we will also compute the set of possible targets for invoke-
* interface and invoke-virtual instructions that target a library method, and add the
diff --git a/src/test/java/com/android/tools/r8/BackportedMethodListTest.java b/src/test/java/com/android/tools/r8/BackportedMethodListTest.java
index 6ed9d46..706126c 100644
--- a/src/test/java/com/android/tools/r8/BackportedMethodListTest.java
+++ b/src/test/java/com/android/tools/r8/BackportedMethodListTest.java
@@ -155,8 +155,8 @@
.setConsumer(new ListStringConsumer())
.build());
fail("Expected failure");
- } catch (Throwable e) {
- // This should throw a CompilationFailedException but an assertion is failing first.
+ } catch (CompilationFailedException e) {
+ // Expected.
}
}
}
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index cf095b1..9740064 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -632,18 +632,9 @@
@Test
public void desugaredLibrary() throws CompilationFailedException {
- D8Command d8Command =
- parse(
- "--desugared-lib",
- "src/library_desugar/desugar_jdk_libs.json",
- "--lib",
- ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
+ D8Command d8Command = parse("--desugared-lib", "src/library_desugar/desugar_jdk_libs.json");
assertFalse(
- d8Command
- .getInternalOptions()
- .machineDesugaredLibrarySpecification
- .getRewriteType()
- .isEmpty());
+ d8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/L8CommandTest.java b/src/test/java/com/android/tools/r8/L8CommandTest.java
index 358d863..e1902f4 100644
--- a/src/test/java/com/android/tools/r8/L8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/L8CommandTest.java
@@ -355,17 +355,9 @@
@Test
public void desugaredLibrary() throws CompilationFailedException {
L8Command l8Command =
- parse(
- "--desugared-lib",
- ToolHelper.getDesugarLibJsonForTesting().toString(),
- "--lib",
- ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
+ parse("--desugared-lib", ToolHelper.getDesugarLibJsonForTesting().toString());
assertFalse(
- l8Command
- .getInternalOptions()
- .machineDesugaredLibrarySpecification
- .getRewriteType()
- .isEmpty());
+ l8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
}
private void checkSingleForceAllAssertion(
diff --git a/src/test/java/com/android/tools/r8/L8TestBuilder.java b/src/test/java/com/android/tools/r8/L8TestBuilder.java
index 7a42ab1..44202c6 100644
--- a/src/test/java/com/android/tools/r8/L8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/L8TestBuilder.java
@@ -108,10 +108,6 @@
return this;
}
- public TestDiagnosticMessages getDiagnosticMessages() {
- return state.getDiagnosticsMessages();
- }
-
public L8TestBuilder setDebug() {
this.mode = CompilationMode.DEBUG;
return this;
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index 325344f..0b48fc2 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -763,18 +763,9 @@
@Test
public void desugaredLibrary() throws CompilationFailedException {
- R8Command r8Command =
- parse(
- "--desugared-lib",
- "src/library_desugar/desugar_jdk_libs.json",
- "--lib",
- ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
+ R8Command r8Command = parse("--desugared-lib", "src/library_desugar/desugar_jdk_libs.json");
assertFalse(
- r8Command
- .getInternalOptions()
- .machineDesugaredLibrarySpecification
- .getRewriteType()
- .isEmpty());
+ r8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
}
@Test
@@ -784,16 +775,10 @@
parse(
"--desugared-lib",
"src/library_desugar/desugar_jdk_libs.json",
- "--lib",
- ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
"--desugared-lib-pg-conf-output",
pgout.toString());
assertFalse(
- r8Command
- .getInternalOptions()
- .machineDesugaredLibrarySpecification
- .getRewriteType()
- .isEmpty());
+ r8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
index c8f932d..72cdc59 100644
--- a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
@@ -3,15 +3,23 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.LibraryDesugaringTestConfiguration;
-import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import java.util.List;
import java.util.function.Consumer;
@@ -25,15 +33,19 @@
private static final String EXPECTED = StringUtils.lines("Y", "89");
- @Parameterized.Parameters(name = "{0}")
+ @Parameterized.Parameters(name = "{0}, old-rt:{1}")
public static List<Object[]> data() {
- return buildParameters(getTestParameters().withAllRuntimesAndApiLevels().build());
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
}
private final TestParameters parameters;
+ private final boolean rtWithoutConsumer;
- public InvokeSuperToRewrittenDefaultMethodTest(TestParameters parameters) {
+ public InvokeSuperToRewrittenDefaultMethodTest(
+ TestParameters parameters, boolean rtWithoutConsumer) {
this.parameters = parameters;
+ this.rtWithoutConsumer = rtWithoutConsumer;
}
private boolean needsDefaultInterfaceMethodDesugaring() {
@@ -53,15 +65,35 @@
@Test
public void testDesugaring() throws Exception {
assumeTrue(needsDefaultInterfaceMethodDesugaring());
- testForD8()
- .addInnerClasses(InvokeSuperToRewrittenDefaultMethodTest.class)
- .setMinApi(parameters.getApiLevel())
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .enableCoreLibraryDesugaring(
- LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
- .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertNoMessages)
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutput(EXPECTED);
+ try {
+ testForD8()
+ .addInnerClasses(InvokeSuperToRewrittenDefaultMethodTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .addLibraryFiles(
+ rtWithoutConsumer
+ ? ToolHelper.getAndroidJar(AndroidApiLevel.B)
+ : ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .enableCoreLibraryDesugaring(
+ LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
+ .compileWithExpectedDiagnostics(
+ diagnostics -> {
+ if (rtWithoutConsumer) {
+ diagnostics.assertOnlyErrors();
+ // TODO(b/158543011): Should fail with a nice user error for invalid library.
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticType(ExceptionDiagnostic.class),
+ diagnosticMessage(containsString("AssertionError"))));
+ } else {
+ diagnostics.assertNoMessages();
+ }
+ })
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ assertFalse(rtWithoutConsumer);
+ } catch (CompilationFailedException e) {
+ assertTrue(rtWithoutConsumer);
+ }
}
public interface CharConsumer extends Consumer<Character>, IntConsumer {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
index b5e5c03..6b54606 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
@@ -73,13 +73,11 @@
}
private void configurationForProgramCompilation(InternalOptions options) {
- setDesugaredLibrarySpecificationForTesting(
- options, configurationAlternative3(options, false, parameters));
+ options.desugaredLibrarySpecification = configurationAlternative3(options, false, parameters);
}
private void configurationForLibraryCompilation(InternalOptions options) {
- setDesugaredLibrarySpecificationForTesting(
- options, configurationAlternative3(options, true, parameters));
+ options.desugaredLibrarySpecification = configurationAlternative3(options, true, parameters);
}
@Test
@@ -143,7 +141,10 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
.addLibraryFiles(getLibraryFile())
- .addOptionsModification(this::configurationForProgramCompilation)
+ .addOptionsModification(
+ options ->
+ options.desugaredLibrarySpecification =
+ configurationAlternative3(options, false, parameters))
.addInnerClasses(BufferedReaderTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -169,7 +170,10 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
.addLibraryFiles(getLibraryFile())
- .addOptionsModification(this::configurationForProgramCompilation)
+ .addOptionsModification(
+ options ->
+ options.desugaredLibrarySpecification =
+ configurationAlternative3(options, false, parameters))
.addInnerClasses(BufferedReaderTest.class)
.addKeepMainRule(TestClass.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
index 473153c..d1e9746 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
@@ -10,11 +10,17 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LegacyToHumanSpecificationConverter;
import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
@@ -34,15 +40,19 @@
private final TestParameters parameters;
private final boolean shrinkDesugaredLibrary;
+ private final boolean machineSpec;
- @Parameters(name = "machine: {0}, shrink: {1}")
+ @Parameters(name = "machine: {0}, {2}, shrink: {1}")
public static List<Object[]> data() {
return buildParameters(
BooleanUtils.values(),
+ BooleanUtils.values(),
getTestParameters().withDexRuntimes().withAllApiLevels().build());
}
- public CustomCollectionTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ public CustomCollectionTest(
+ boolean machineSpec, boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ this.machineSpec = machineSpec;
this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
this.parameters = parameters;
}
@@ -50,6 +60,22 @@
private final String EXECUTOR =
"com.android.tools.r8.desugar.desugaredlibrary.CustomCollectionTest$Executor";
+ private void setMachineSpec(InternalOptions opt) {
+ if (!machineSpec) {
+ return;
+ }
+ try {
+ HumanDesugaredLibrarySpecification human =
+ new LegacyToHumanSpecificationConverter()
+ .convert(opt.desugaredLibrarySpecification, getLibraryFile(), opt);
+ MachineDesugaredLibrarySpecification machine =
+ new HumanToMachineSpecificationConverter().convert(human, getLibraryFile(), opt);
+ opt.testing.machineDesugaredLibrarySpecification = machine;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Test
public void testCustomCollectionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
@@ -57,6 +83,7 @@
testForD8()
.addLibraryFiles(getLibraryFile())
.addInnerClasses(CustomCollectionTest.class)
+ .addOptionsModification(this::setMachineSpec)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
@@ -79,6 +106,7 @@
Path jar =
testForD8(Backend.CF)
.addInnerClasses(CustomCollectionTest.class)
+ .addOptionsModification(this::setMachineSpec)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
@@ -134,6 +162,7 @@
testForR8(Backend.DEX)
.addLibraryFiles(getLibraryFile())
.addInnerClasses(CustomCollectionTest.class)
+ .addOptionsModification(this::setMachineSpec)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java
index e27dda9..3e7d97d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java
@@ -43,9 +43,10 @@
"",
false,
Collections.emptyList(),
- options ->
- setDesugaredLibrarySpecificationForTesting(
- options, chmOnlyConfiguration(options, true, parameters)));
+ options -> {
+ options.desugaredLibrarySpecification =
+ chmOnlyConfiguration(options, true, parameters);
+ });
CodeInspector inspector = new CodeInspector(desugaredLib);
assert inspector.clazz("j$.util.concurrent.ConcurrentHashMap").isPresent();
}
@@ -60,9 +61,10 @@
"-keep class * { *; }",
true,
Collections.emptyList(),
- options ->
- setDesugaredLibrarySpecificationForTesting(
- options, chmOnlyConfiguration(options, true, parameters)));
+ options -> {
+ options.desugaredLibrarySpecification =
+ chmOnlyConfiguration(options, true, parameters);
+ });
CodeInspector inspector = new CodeInspector(desugaredLib);
assert inspector.clazz("j$.util.concurrent.ConcurrentHashMap").isPresent();
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
index 819aa45..e353126 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
@@ -5,19 +5,15 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.fail;
import com.android.tools.r8.L8Command;
-import com.android.tools.r8.L8TestBuilder;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.StringResource;
-import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -29,7 +25,6 @@
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Collections;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,33 +45,6 @@
}
@Test
- public void testInvalidLibrary() throws Exception {
- Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
- L8TestBuilder l8TestBuilder =
- testForL8(parameters.getApiLevel())
- .addProgramFiles(Collections.singleton(ToolHelper.getDesugarJDKLibs()))
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.L))
- .setDesugarJDKLibsConfiguration(ToolHelper.DESUGAR_LIB_CONVERSIONS);
- try {
- l8TestBuilder.compile();
- fail();
- } catch (AssertionError ae) {
- // Expected since the library is invalid.
- }
- TestDiagnosticMessages diagnosticMessages = l8TestBuilder.getDiagnosticMessages();
- diagnosticMessages.assertOnlyWarnings();
- assertEquals(diagnosticMessages.getWarnings().size(), 1);
- assertTrue(
- diagnosticMessages
- .getWarnings()
- .get(0)
- .getDiagnosticMessage()
- .contains(
- "Desugared library requires to be compiled with a library file of API greater or"
- + " equal to"));
- }
-
- @Test
public void testDesugaredLibraryContentD8() throws Exception {
Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
CodeInspector inspector = new CodeInspector(buildDesugaredLibrary(parameters.getApiLevel()));
@@ -121,16 +89,11 @@
ToolHelper.runL8(l8Builder.build(), options -> {});
CodeInspector codeInspector = new CodeInspector(desugaredLib);
assertCorrect(codeInspector);
- assertOneWarning(diagnosticsHandler);
+ assertNoWarningsErrors(diagnosticsHandler);
}
- private void assertOneWarning(TestDiagnosticMessagesImpl diagnosticsHandler) {
- assertEquals(1, diagnosticsHandler.getWarnings().size());
- String msg = diagnosticsHandler.getWarnings().get(0).getDiagnosticMessage();
- assertTrue(
- msg.contains(
- "The following library types, prefixed by java., are present both as library and non"
- + " library classes"));
+ private void assertNoWarningsErrors(TestDiagnosticMessagesImpl diagnosticsHandler) {
+ assertTrue(diagnosticsHandler.getWarnings().isEmpty());
assertTrue(diagnosticsHandler.getErrors().isEmpty());
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index a3832c1..34faa58 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -67,18 +67,6 @@
return property.contains("jdk11");
}
- public void setDesugaredLibrarySpecificationForTesting(
- InternalOptions options, LegacyDesugaredLibrarySpecification specification) {
- try {
- options.setDesugaredLibrarySpecificationForTesting(
- specification,
- ToolHelper.getDesugarJDKLibs(),
- ToolHelper.getAndroidJar(AndroidApiLevel.R));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
// For conversions tests, we need DexRuntimes where classes to convert are present (DexRuntimes
// above N and O depending if Stream or Time APIs are used), but we need to compile the program
// with a minAPI below to force the use of conversions.
@@ -101,7 +89,7 @@
protected Path getLibraryFile() {
return isJDK11DesugaredLibrary()
- ? ToolHelper.getAndroidJar(AndroidApiLevel.R)
+ ? ToolHelper.getAndroidJar(AndroidApiLevel.S)
: ToolHelper.getAndroidJar(AndroidApiLevel.P);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
index e1a8586..0c61a06 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
@@ -4,9 +4,6 @@
package com.android.tools.r8.desugar.desugaredlibrary;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.L8Command;
import com.android.tools.r8.OutputMode;
@@ -68,15 +65,6 @@
Arrays.asList(FUNCTION_KEEP.split(System.lineSeparator())), Origin.unknown());
}
ToolHelper.runL8(l8Builder.build(), options -> {});
- assertEquals(diagnosticsHandler.getWarnings().size(), 1);
- diagnosticsHandler.assertNoErrors();
- assertTrue(
- diagnosticsHandler
- .getWarnings()
- .get(0)
- .getDiagnosticMessage()
- .contains(
- "The following library types, prefixed by java., are present both as library and"
- + " non library classes:"));
+ diagnosticsHandler.assertNoMessages();
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InconsistentPrefixTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InconsistentPrefixTest.java
new file mode 100644
index 0000000..b1f57e1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InconsistentPrefixTest.java
@@ -0,0 +1,59 @@
+// 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.desugar.desugaredlibrary;
+
+import static org.hamcrest.CoreMatchers.containsString;
+
+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.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.jasmin.JasminBuilder;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+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 InconsistentPrefixTest extends TestBase {
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public InconsistentPrefixTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
+ @Test(expected = CompilationFailedException.class)
+ public void testNoInconsistentPrefixes() throws Exception {
+ Map<String, String> x = new HashMap<>();
+ x.put("pkg.sub", "p$.bus");
+ x.put("pkg", "p$");
+
+ JasminBuilder jasminBuilder = new JasminBuilder();
+ jasminBuilder.addClass("pkg/notsub/A");
+ jasminBuilder.addClass("pkg/sub/A");
+ Path inputJar = temp.getRoot().toPath().resolve("input.jar");
+ jasminBuilder.writeJar(inputJar);
+
+ testForD8()
+ .addProgramFiles(inputJar)
+ .addOptionsModification(
+ options ->
+ options.desugaredLibrarySpecification =
+ LegacyDesugaredLibrarySpecification.withOnlyRewritePrefixForTesting(x, options))
+ .compileWithExpectedDiagnostics(
+ diagnostics -> {
+ diagnostics.assertErrorMessageThatMatches(
+ containsString("Inconsistent prefix in desugared library"));
+ });
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
index 371443d..88f3ca9 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
@@ -5,12 +5,15 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.BooleanUtils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -28,6 +31,7 @@
public class J$ExtensionTest extends DesugaredLibraryTestBase {
private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
private static final String MAIN_CLASS_NAME = "Main";
private static final String MAIN_CLASS =
@@ -51,12 +55,14 @@
+ "}";
private static Path[] compiledClasses = new Path[2];
- @Parameters(name = "{0}")
+ @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
public static List<Object[]> data() {
- return buildParameters(getTestParameters().withAllRuntimes().withAllApiLevels().build());
+ return buildParameters(
+ BooleanUtils.values(), getTestParameters().withAllRuntimes().withAllApiLevels().build());
}
- public J$ExtensionTest(TestParameters parameters) {
+ public J$ExtensionTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
this.parameters = parameters;
}
@@ -86,6 +92,7 @@
@Test
public void testJ$ExtensionNoDesugaring() throws Exception {
+ Assume.assumeFalse(shrinkDesugaredLibrary);
String stderr;
if (parameters.isCfRuntime()) {
stderr =
@@ -103,31 +110,24 @@
.assertFailure()
.getStdErr();
}
- assertError(stderr, false);
+ assertError(stderr);
}
- private void assertError(String stderr, boolean desugaring) {
- if (parameters.isCfRuntime()) {
- if (parameters.getRuntime().asCf().getVm() == CfVm.JDK8) {
- assertTrue(
- stderr.contains("java.lang.SecurityException: Prohibited package name: java.time"));
- } else {
- assertTrue(stderr.contains("java.lang.ClassNotFoundException: java.time.LocalTimeAccess"));
- }
- return;
- }
- assert !parameters.isCfRuntime();
- if (!desugaring) {
- if (parameters.getDexRuntimeVersion().isOlderThanOrEqual(Version.V6_0_1)) {
- assertTrue(stderr.contains("java.lang.NoClassDefFoundError"));
- } else if (parameters.getDexRuntimeVersion() == Version.V7_0_0) {
- assertTrue(stderr.contains("java.lang.ClassNotFoundException"));
- }
- return;
- }
- if (parameters.getDexRuntimeVersion() == Version.V8_1_0) {
- // On Android 8 the library package private method is accessible.
- assertTrue(stderr.contains("java.lang.NullPointerException"));
+ private void assertError(String stderr) {
+ if (parameters.isCfRuntime() && parameters.getRuntime().asCf().getVm() == CfVm.JDK8) {
+ assertTrue(
+ stderr.contains("java.lang.SecurityException: Prohibited package name: java.time"));
+ } else if (parameters.isCfRuntime()) {
+ assertTrue(stderr.contains("java.lang.ClassNotFoundException: java.time.LocalTimeAccess"));
+ } else if (parameters
+ .getRuntime()
+ .asDex()
+ .getVm()
+ .getVersion()
+ .isOlderThanOrEqual(Version.V6_0_1)) {
+ assertTrue(stderr.contains("java.lang.NoClassDefFoundError"));
+ } else if (parameters.getRuntime().asDex().getVm().getVersion() == Version.V7_0_0) {
+ assertTrue(stderr.contains("java.lang.ClassNotFoundException"));
} else {
assertTrue(stderr.contains("java.lang.IllegalAccessError"));
}
@@ -140,18 +140,19 @@
Assume.assumeTrue(requiresTimeDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
- String stdErr =
- testForD8()
- .addLibraryFiles(getLibraryFile())
- .addProgramFiles(compiledClasses)
- .setMinApi(parameters.getApiLevel())
- .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
- .compile()
- .addDesugaredCoreLibraryRunClassPath(
- this::buildDesugaredLibrary, parameters.getApiLevel())
- .run(parameters.getRuntime(), MAIN_CLASS_NAME)
- .assertFailure()
- .getStdErr();
- assertError(stdErr, true);
+ try {
+ testForD8()
+ .addLibraryFiles(getLibraryFile())
+ .addProgramFiles(compiledClasses)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile();
+ fail();
+ } catch (CompilationFailedException e) {
+ assertTrue(
+ e.getCause()
+ .getMessage()
+ .contains("Cannot compile program class java.time.LocalTimeAccess"));
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
index d78df31..6598d6b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
@@ -144,22 +144,16 @@
.map(TypeSubject::toString)
.collect(Collectors.toSet());
assertEquals(expectedCatchGuards, foundCatchGuards);
- if (!(parameters
- .getApiLevel()
- .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport())
- && isR8)) {
+
+ if (isR8) {
+ assertThat(
+ inspector.clazz(TemporalAccessorImpl.class).uniqueMethodWithFinalName("query"),
+ not(isPresent()));
+ } else {
assertThat(
inspector.clazz(TemporalAccessorImplSub.class).uniqueMethodWithFinalName("query"),
CodeMatchers.invokesMethod(
- null, inspector.clazz(TemporalAccessorImpl.class).getFinalName(), "query", null));
- } else {
- String holder =
- requiresTimeDesugaring(parameters)
- ? "j$.time.temporal.TemporalAccessor"
- : "java.time.temporal.TemporalAccessor";
- assertThat(
- inspector.clazz(TemporalAccessorImplSub.class).uniqueMethodWithFinalName("query"),
- CodeMatchers.invokesMethod(null, holder, "query", null));
+ null, TemporalAccessorImpl.class.getTypeName(), "query", null));
}
if (parameters
.getApiLevel()
@@ -169,7 +163,9 @@
not(isPresent()));
} else {
assertThat(
- inspector.clazz(TemporalAccessorImpl.class).uniqueMethodWithFinalName("query"),
+ inspector
+ .clazz(isR8 ? TemporalAccessorImplSub.class : TemporalAccessorImpl.class)
+ .uniqueMethodWithFinalName("query"),
CodeMatchers.invokesMethod(
null, "j$.time.temporal.TemporalAccessor$-CC", "$default$query", null));
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java
index de87214..981edea 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java
@@ -11,7 +11,6 @@
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
-import java.util.function.Predicate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -166,14 +165,6 @@
System.out.println("true");
System.out.println(spliterator.hasCharacteristics(Spliterator.IMMUTABLE));
System.out.println("false");
-
- spliterator = ((Set<String>) new CustomLinkedHashSetForceForwarding<String>()).spliterator();
- System.out.println(spliterator.hasCharacteristics(Spliterator.DISTINCT));
- System.out.println("true");
- System.out.println(spliterator.hasCharacteristics(Spliterator.ORDERED));
- System.out.println("true");
- System.out.println(spliterator.hasCharacteristics(Spliterator.IMMUTABLE));
- System.out.println("false");
}
}
@@ -207,13 +198,4 @@
return super.spliterator();
}
}
-
- // The over method force the forwarding methods to be installed.
- static class CustomLinkedHashSetForceForwarding<E> extends LinkedHashSet<E> {
-
- @Override
- public boolean removeIf(Predicate<? super E> filter) {
- return super.removeIf(filter);
- }
- }
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
index 1208414..d5300ad 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
@@ -118,8 +118,8 @@
L8.run(
L8Command.builder()
.addLibraryFiles(getLibraryFile())
- .addLibraryFiles(ToolHelper.getDesugarJDKLibs())
.addProgramFiles(JDK_11_JAVA_BASE_EXTENSION_COMPILED_FILES)
+ .addClasspathFiles(ToolHelper.getDesugarJDKLibs())
.addDesugaredLibraryConfiguration(
StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()))
.setMinApiLevel(AndroidApiLevel.B.getLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
index f3caf57..abdf5c5 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
@@ -99,13 +99,13 @@
}
private void configurationForProgramCompilation(InternalOptions options) {
- setDesugaredLibrarySpecificationForTesting(
- options, desugaredLibrarySpecification(options, false, parameters));
+ options.desugaredLibrarySpecification =
+ desugaredLibrarySpecification(options, false, parameters);
}
private void configurationForLibraryCompilation(InternalOptions options) {
- setDesugaredLibrarySpecificationForTesting(
- options, desugaredLibrarySpecification(options, true, parameters));
+ options.desugaredLibrarySpecification =
+ desugaredLibrarySpecification(options, true, parameters);
}
private Matcher<MethodSubject> invokesObjectsCompare(String holder) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
index 9b1804e..359a18c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
@@ -7,7 +7,6 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyRewritingFlags;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyTopLevelFlags;
@@ -15,7 +14,6 @@
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import java.io.IOException;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,15 +55,9 @@
.putBackportCoreLibraryMember("java.lang.DesugarMath", "java.lang.Math")
.putRetargetCoreLibMember("java.util.Date#toInstant", "java.util.DesugarDate")
.build();
- try {
- options.setDesugaredLibrarySpecificationForTesting(
- new LegacyDesugaredLibrarySpecification(
- LegacyTopLevelFlags.testing(), rewritingFlags, true),
- ToolHelper.getDesugarJDKLibs(),
- ToolHelper.getAndroidJar(AndroidApiLevel.R));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ options.desugaredLibrarySpecification =
+ new LegacyDesugaredLibrarySpecification(
+ LegacyTopLevelFlags.testing(), rewritingFlags, true, options.itemFactory);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
index e629c47..6bf49a0 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
@@ -5,7 +5,13 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LegacyToHumanSpecificationConverter;
import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import java.io.IOException;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZonedDateTime;
@@ -25,15 +31,19 @@
private final TestParameters parameters;
private final boolean shrinkDesugaredLibrary;
+ private final boolean machineSpec;
@Parameters(name = "machine: {0}, {2}, shrink: {1}")
public static List<Object[]> data() {
return buildParameters(
BooleanUtils.values(),
+ BooleanUtils.values(),
getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build());
}
- public RetargetOverrideTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ public RetargetOverrideTest(
+ boolean machineSpec, boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ this.machineSpec = machineSpec;
this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
this.parameters = parameters;
}
@@ -44,6 +54,7 @@
Path desugaredTwice =
testForD8(Backend.CF)
.addLibraryFiles(getLibraryFile())
+ .addOptionsModification(this::setMachineSpec)
.addProgramFiles(
testForD8(Backend.CF)
.addLibraryFiles(getLibraryFile())
@@ -65,6 +76,7 @@
stdout =
testForD8(Backend.DEX)
.addProgramFiles(desugaredTwice)
+ .addOptionsModification(this::setMachineSpec)
.setMinApi(parameters.getApiLevel())
.disableDesugaring()
.compile()
@@ -95,6 +107,22 @@
assertLines2By2Correct(stdout);
}
+ private void setMachineSpec(InternalOptions opt) {
+ if (!machineSpec) {
+ return;
+ }
+ try {
+ HumanDesugaredLibrarySpecification human =
+ new LegacyToHumanSpecificationConverter()
+ .convert(opt.desugaredLibrarySpecification, getLibraryFile(), opt);
+ MachineDesugaredLibrarySpecification machine =
+ new HumanToMachineSpecificationConverter().convert(human, getLibraryFile(), opt);
+ opt.testing.machineDesugaredLibrarySpecification = machine;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Test
public void testRetargetOverrideD8() throws Exception {
Assume.assumeTrue(parameters.getRuntime().isDex());
@@ -102,6 +130,7 @@
String stdout =
testForD8()
.addLibraryFiles(getLibraryFile())
+ .addOptionsModification(this::setMachineSpec)
.addInnerClasses(RetargetOverrideTest.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.setMinApi(parameters.getApiLevel())
@@ -127,6 +156,7 @@
String stdout =
testForR8(Backend.DEX)
.addLibraryFiles(getLibraryFile())
+ .addOptionsModification(this::setMachineSpec)
.addKeepMainRule(Executor.class)
.addInnerClasses(RetargetOverrideTest.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java
index 7abed46..f9d1828 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java
@@ -58,7 +58,6 @@
.setMinApi(AndroidApiLevel.B)
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
- .addLibraryFiles(getLibraryFile())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.addDesugaredCoreLibraryRunClassPath(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java
index a57140b..6691cb1 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java
@@ -66,8 +66,8 @@
.build();
LegacyDesugaredLibrarySpecification specification =
new LegacyDesugaredLibrarySpecification(
- LegacyTopLevelFlags.testing(), rewritingFlags, l8Compilation);
- setDesugaredLibrarySpecificationForTesting(options, specification);
+ LegacyTopLevelFlags.testing(), rewritingFlags, l8Compilation, options.itemFactory);
+ options.desugaredLibrarySpecification = specification;
}
@Test
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 957515a..aa97e55 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
@@ -87,10 +87,9 @@
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.addOptionsModification(
opt ->
- setDesugaredLibrarySpecificationForTesting(
- opt,
+ opt.desugaredLibrarySpecification =
configurationWithSupportAllCallbacksFromLibrary(
- opt, false, parameters, supportAllCallbacksFromLibrary)))
+ opt, false, parameters, supportAllCallbacksFromLibrary))
.compile()
.inspect(this::assertDoubleForEach)
.inspect(this::assertWrapperMethodsPresent)
@@ -152,10 +151,9 @@
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.addOptionsModification(
opt ->
- setDesugaredLibrarySpecificationForTesting(
- opt,
+ opt.desugaredLibrarySpecification =
configurationWithSupportAllCallbacksFromLibrary(
- opt, false, parameters, supportAllCallbacksFromLibrary)))
+ opt, false, parameters, supportAllCallbacksFromLibrary))
.compile()
.inspect(this::assertDoubleForEach)
.inspect(this::assertWrapperMethodsPresent)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
index b966b00..6b7d86e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
@@ -71,10 +71,9 @@
this.buildDesugaredLibrary(
api,
opt ->
- setDesugaredLibrarySpecificationForTesting(
- opt,
+ opt.desugaredLibrarySpecification =
configurationWithSupportAllCallbacksFromLibrary(
- opt, true, parameters, supportAllCallbacksFromLibrary))));
+ opt, true, parameters, supportAllCallbacksFromLibrary)));
return desugaredLibBox.get();
},
AndroidApiLevel.B)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
index aaab5cb..a669527 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
@@ -58,7 +58,6 @@
.setMinApi(parameters.getApiLevel())
.addProgramClasses(BaselineExecutor.class)
.addLibraryClasses(CustomLibClass.class)
- .addLibraryFiles(getLibraryFile())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.addDesugaredCoreLibraryRunClassPath(
@@ -99,7 +98,6 @@
.setMinApi(parameters.getApiLevel())
.addProgramClasses(TryCatchExecutor.class)
.addLibraryClasses(CustomLibClass.class)
- .addLibraryFiles(getLibraryFile())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.addDesugaredCoreLibraryRunClassPath(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java
index 3b6ae0a..2bd50b2 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java
@@ -270,7 +270,6 @@
.addProgramFiles(testNGSupportProgramFiles())
.addOptionsModification(opt -> opt.testing.trackDesugaredAPIConversions = true)
.addLibraryFiles(getLibraryFile())
- .addLibraryFiles(JDK_11_JAVA_BASE_EXTENSION_CLASSES_DIR)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.allowStdoutMessages()
@@ -304,7 +303,6 @@
.addProgramFiles(testNGSupportProgramFiles())
.addOptionsModification(opt -> opt.testing.trackDesugaredAPIConversions = true)
.addLibraryFiles(getLibraryFile())
- .addLibraryFiles(JDK_11_JAVA_BASE_EXTENSION_CLASSES_DIR)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java b/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
index bf94752..f3103f1 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
@@ -12,13 +12,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.memberrebinding.b135627418.library.Drawable;
import com.android.tools.r8.memberrebinding.b135627418.library.DrawableWrapper;
import com.android.tools.r8.memberrebinding.b135627418.library.InsetDrawable;
-import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -78,27 +75,11 @@
com.android.tools.r8.memberrebinding.b135627418.runtime.InsetDrawable.class)
.setMinApi(parameters.getRuntime())
.addOptionsModification(
- options -> {
- options.desugaredLibrarySpecification =
- LegacyDesugaredLibrarySpecification.withOnlyRewritePrefixForTesting(
- ImmutableMap.of(packageName + ".runtime", packageName + ".library"),
- options);
- DexType type =
- options
- .dexItemFactory()
- .createType(
- DescriptorUtils.javaTypeToDescriptor(
- packageName + ".runtime.InsetDrawable"));
- DexType rewrittenType =
- options
- .dexItemFactory()
- .createType(
- DescriptorUtils.javaTypeToDescriptor(
- packageName + ".library.InsetDrawable"));
- options.machineDesugaredLibrarySpecification =
- MachineDesugaredLibrarySpecification.withOnlyRewriteTypeForTesting(
- ImmutableMap.of(type, rewrittenType));
- })
+ options ->
+ options.desugaredLibrarySpecification =
+ LegacyDesugaredLibrarySpecification.withOnlyRewritePrefixForTesting(
+ ImmutableMap.of(packageName + ".runtime", packageName + ".library"),
+ options))
.compile();
testForR8(parameters.getBackend())