fix merge issues
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 4040acd..8a4a364 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -129,6 +129,14 @@
}
}
+ public DexAnnotationSet annotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(DexAnnotationSet annotations) {
+ this.annotations = annotations;
+ }
+
public Iterable<DexEncodedField> fields() {
return fields(Predicates.alwaysTrue());
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index bdd4968..f6522de 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -318,7 +318,7 @@
// 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 (!libraryHolder.isInterface()
- && !appView.rewritePrefix.hasRewrittenType(libraryHolder.type, appView)) {
+ && !appView.rewritePrefix.hasRewrittenType(libraryHolder.type)) {
// Here we use step-3 of resolution to find a maximally specific default interface method.
target =
appView
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
deleted file mode 100644
index 5ce5bb8..0000000
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.ir.desugar;
-
-import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.ClassAccessFlags;
-import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexLibraryClass;
-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.ParameterAnnotationsList;
-import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.utils.StringDiagnostic;
-import com.android.tools.r8.utils.collections.SortedProgramMethodSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.function.Consumer;
-
-public class DesugaredLibraryRetargeter {
-
- public static final String DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX =
- "$r8$retargetLibraryMember$virtualDispatch";
-
- private final AppView<?> appView;
- private final Map<DexMethod, DexMethod> retargetLibraryMember = new IdentityHashMap<>();
- // Map nonFinalRewrite hold a methodName -> method mapping for methods which are rewritten while
- // the holder is non final. In this case d8 needs to force resolution of given methods to see if
- // the invoke needs to be rewritten.
- private final Map<DexString, List<DexMethod>> nonFinalHolderRewrites = new IdentityHashMap<>();
- // Non final virtual library methods requiring generation of emulated dispatch.
- private final Set<DexEncodedMethod> emulatedDispatchMethods = Sets.newIdentityHashSet();
-
- public DesugaredLibraryRetargeter(AppView<?> appView) {
- this.appView = appView;
- if (appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
- return;
- }
- new RetargetingSetup().setUpRetargeting();
- }
-
- public static void checkForAssumedLibraryTypes(AppView<?> appView) {
- Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
- appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
- for (DexString methodName : retargetCoreLibMember.keySet()) {
- for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
- DexClass typeClass = appView.definitionFor(inType);
- if (typeClass == null) {
- warnMissingRetargetCoreLibraryMember(inType, appView);
- }
- }
- }
- }
-
- private static void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
- StringDiagnostic warning =
- new StringDiagnostic(
- "Cannot retarget core library member "
- + type.getName()
- + " because the class is missing.");
- appView.options().reporter.warning(warning);
- }
-
- // Used by the ListOfBackportedMethods utility.
- void visit(Consumer<DexMethod> consumer) {
- retargetLibraryMember.keySet().forEach(consumer);
- }
-
- public void desugar(IRCode code) {
- if (retargetLibraryMember.isEmpty()) {
- return;
- }
-
- InstructionListIterator iterator = code.instructionListIterator();
- while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
- if (!instruction.isInvokeMethod()) {
- continue;
- }
-
- InvokeMethod invoke = instruction.asInvokeMethod();
- DexMethod retarget = getRetargetLibraryMember(invoke.getInvokedMethod());
- if (retarget == null) {
- if (!matchesNonFinalHolderRewrite(invoke.getInvokedMethod())) {
- continue;
- }
- // We need to force resolution, even on d8, to know if the invoke has to be rewritten.
- ResolutionResult resolutionResult =
- appView
- .appInfoForDesugaring()
- .resolveMethod(invoke.getInvokedMethod(), invoke.getInterfaceBit());
- if (resolutionResult.isFailedResolution()) {
- continue;
- }
- DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
- assert singleTarget != null;
- retarget = getRetargetLibraryMember(singleTarget.method);
- if (retarget == null) {
- continue;
- }
- }
-
- // Due to emulated dispatch, we have to rewrite invoke-super differently or we end up in
- // infinite loops. We do direct resolution. This is a very uncommon case.
- if (invoke.isInvokeSuper() && matchesNonFinalHolderRewrite(invoke.getInvokedMethod())) {
- DexEncodedMethod dexEncodedMethod =
- appView
- .appInfoForDesugaring()
- .lookupSuperTarget(invoke.getInvokedMethod(), code.context());
- // Final methods can be rewritten as a normal invoke.
- if (dexEncodedMethod != null && !dexEncodedMethod.isFinal()) {
- DexMethod retargetMethod =
- appView
- .options()
- .desugaredLibraryConfiguration
- .retargetMethod(dexEncodedMethod, appView);
- if (retargetMethod != null) {
- iterator.replaceCurrentInstruction(
- new InvokeStatic(retargetMethod, invoke.outValue(), invoke.arguments()));
- }
- continue;
- }
- }
-
- iterator.replaceCurrentInstruction(
- new InvokeStatic(retarget, invoke.outValue(), invoke.inValues()));
- }
- }
-
- private DexMethod getRetargetLibraryMember(DexMethod method) {
- Map<DexType, DexType> backportCoreLibraryMembers =
- appView.options().desugaredLibraryConfiguration.getBackportCoreLibraryMember();
- if (backportCoreLibraryMembers.containsKey(method.holder)) {
- DexType newHolder = backportCoreLibraryMembers.get(method.holder);
- return appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
- }
- return retargetLibraryMember.get(method);
- }
-
- private boolean matchesNonFinalHolderRewrite(DexMethod method) {
- List<DexMethod> dexMethods = nonFinalHolderRewrites.get(method.name);
- if (dexMethods == null) {
- return false;
- }
- for (DexMethod dexMethod : dexMethods) {
- if (method.match(dexMethod)) {
- return true;
- }
- }
- return false;
- }
-
- private class RetargetingSetup {
-
- private void setUpRetargeting() {
- Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
- appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
- 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<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass);
- for (DexEncodedMethod encodedMethod : found) {
- if (!typeClass.isFinal()) {
- nonFinalHolderRewrites.putIfAbsent(encodedMethod.method.name, new ArrayList<>());
- nonFinalHolderRewrites.get(encodedMethod.method.name).add(encodedMethod.method);
- if (!encodedMethod.isStatic()) {
- if (InterfaceMethodRewriter.isEmulatedInterfaceDispatch(appView, encodedMethod)) {
- // In this case interface method rewriter takes care of it.
- continue;
- } else if (!encodedMethod.isFinal()) {
- // Virtual rewrites require emulated dispatch for inheritance.
- // The call is rewritten to the dispatch holder class instead.
- handleEmulateDispatch(appView, encodedMethod);
- newHolder = dispatchHolderTypeFor(encodedMethod);
- }
- }
- }
- DexProto proto = encodedMethod.method.proto;
- DexMethod method = appView.dexItemFactory().createMethod(inType, proto, methodName);
- retargetLibraryMember.put(
- method, computeRetargetMethod(method, encodedMethod.isStatic(), newHolder));
- }
- }
- }
- }
- }
-
- private DexMethod computeRetargetMethod(DexMethod method, boolean isStatic, DexType newHolder) {
- DexItemFactory factory = appView.dexItemFactory();
- DexProto newProto = isStatic ? method.proto : factory.prependHolderToProto(method);
- return factory.createMethod(newHolder, newProto, method.name);
- }
-
- private List<DexEncodedMethod> findDexEncodedMethodsWithName(
- DexString methodName, DexClass clazz) {
- List<DexEncodedMethod> found = new ArrayList<>();
- for (DexEncodedMethod encodedMethod : clazz.methods()) {
- if (encodedMethod.method.name == methodName) {
- found.add(encodedMethod);
- }
- }
- assert found.size() > 0 : "Should have found a method (library specifications).";
- return found;
- }
-
- private void handleEmulateDispatch(AppView<?> appView, DexEncodedMethod method) {
- emulatedDispatchMethods.add(method);
- if (!appView.options().isDesugaredLibraryCompilation()) {
- // Add rewrite rules so keeps rules are correctly generated in the program.
- DexType dispatchInterfaceType = dispatchInterfaceTypeFor(method);
- appView.rewritePrefix.rewriteType(dispatchInterfaceType, dispatchInterfaceType);
- DexType dispatchHolderType = dispatchHolderTypeFor(method);
- appView.rewritePrefix.rewriteType(dispatchHolderType, dispatchHolderType);
- }
- }
- }
-
- public void synthesizeRetargetClasses(
- DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
- throws ExecutionException {
- new EmulatedDispatchTreeFixer().fixApp(builder, executorService, converter);
- }
-
- // The rewrite of virtual calls requires to go through emulate dispatch. This class is responsible
- // for inserting interfaces on library boundaries and forwarding methods in the program, and to
- // synthesize the interfaces and emulated dispatch classes in the desugared library.
- class EmulatedDispatchTreeFixer {
-
- void fixApp(
- DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
- throws ExecutionException {
- if (appView.options().isDesugaredLibraryCompilation()) {
- synthesizeEmulatedDispatchMethods(builder);
- } else {
- addInterfacesAndForwardingMethods(executorService, converter);
- }
- }
-
- private void addInterfacesAndForwardingMethods(
- ExecutorService executorService, IRConverter converter) throws ExecutionException {
- assert !appView.options().isDesugaredLibraryCompilation();
- Map<DexType, List<DexEncodedMethod>> map = Maps.newIdentityHashMap();
- for (DexEncodedMethod emulatedDispatchMethod : emulatedDispatchMethods) {
- map.putIfAbsent(emulatedDispatchMethod.getHolderType(), new ArrayList<>(1));
- map.get(emulatedDispatchMethod.getHolderType()).add(emulatedDispatchMethod);
- }
- SortedProgramMethodSet addedMethods = SortedProgramMethodSet.create();
- for (DexProgramClass clazz : appView.appInfo().classes()) {
- if (clazz.superType == null) {
- assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
- continue;
- }
- DexClass superclass = appView.definitionFor(clazz.superType);
- // Only performs computation if superclass is a library class, but not object to filter out
- // the most common case.
- if (superclass != null
- && superclass.isLibraryClass()
- && superclass.type != appView.dexItemFactory().objectType) {
- map.forEach(
- (type, methods) -> {
- if (inherit(superclass.asLibraryClass(), type, emulatedDispatchMethods)) {
- addInterfacesAndForwardingMethods(
- clazz, methods, method -> addedMethods.createAndAdd(clazz, method));
- }
- });
- }
- }
- converter.processMethodsConcurrently(addedMethods, executorService);
- }
-
- private boolean inherit(
- DexLibraryClass clazz, DexType typeToInherit, Set<DexEncodedMethod> retarget) {
- DexLibraryClass current = clazz;
- while (current.type != appView.dexItemFactory().objectType) {
- if (current.type == typeToInherit) {
- return true;
- }
- DexClass dexClass = appView.definitionFor(current.superType);
- if (dexClass == null || dexClass.isClasspathClass()) {
- reportInvalidLibrarySupertype(current, retarget);
- return false;
- } else if (dexClass.isProgramClass()) {
- // If dexClass is a program class, then it is already correctly desugared.
- return false;
- }
- current = dexClass.asLibraryClass();
- }
- return false;
- }
-
- private void addInterfacesAndForwardingMethods(
- DexProgramClass clazz,
- List<DexEncodedMethod> methods,
- Consumer<DexEncodedMethod> newForwardingMethodsConsumer) {
- // DesugaredLibraryRetargeter emulate dispatch: insertion of a marker interface & forwarding
- // methods.
- // We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
- // applies up to 24.
- for (DexEncodedMethod method : methods) {
- clazz.addExtraInterfaces(
- Collections.singletonList(dispatchInterfaceTypeFor(method)), appView.dexItemFactory());
- if (clazz.lookupVirtualMethod(method.getReference()) == null) {
- DexEncodedMethod newMethod = createForwardingMethod(method, clazz);
- clazz.addVirtualMethod(newMethod);
- newForwardingMethodsConsumer.accept(newMethod);
- }
- }
- }
-
- private DexEncodedMethod createForwardingMethod(DexEncodedMethod target, DexClass clazz) {
- // 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 =
- appView.options().desugaredLibraryConfiguration.retargetMethod(target, appView);
- assert forwardMethod != null && forwardMethod != target.getReference();
- return DexEncodedMethod.createDesugaringForwardingMethod(
- target, clazz, forwardMethod, appView.dexItemFactory());
- }
-
- private void synthesizeEmulatedDispatchMethods(DexApplication.Builder<?> builder) {
- assert appView.options().isDesugaredLibraryCompilation();
- if (emulatedDispatchMethods.isEmpty()) {
- return;
- }
- ClassAccessFlags itfAccessFlags =
- ClassAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC
- | Constants.ACC_SYNTHETIC
- | Constants.ACC_ABSTRACT
- | Constants.ACC_INTERFACE);
- ClassAccessFlags holderAccessFlags =
- ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
- for (DexEncodedMethod emulatedDispatchMethod : emulatedDispatchMethods) {
- // Dispatch interface.
- DexType interfaceType = dispatchInterfaceTypeFor(emulatedDispatchMethod);
- DexEncodedMethod itfMethod =
- generateInterfaceDispatchMethod(emulatedDispatchMethod, interfaceType);
- BackportedMethodRewriter.synthesizeClassWithUniqueMethod(
- builder,
- itfAccessFlags,
- interfaceType,
- itfMethod,
- "desugared library dispatch interface",
- false,
- appView);
- // Dispatch holder.
- DexType holderType = dispatchHolderTypeFor(emulatedDispatchMethod);
- DexEncodedMethod dispatchMethod =
- generateHolderDispatchMethod(emulatedDispatchMethod, holderType, itfMethod.method);
- BackportedMethodRewriter.synthesizeClassWithUniqueMethod(
- builder,
- holderAccessFlags,
- holderType,
- dispatchMethod,
- "desugared library dispatch class",
- false,
- appView);
- }
- }
-
- private DexEncodedMethod generateInterfaceDispatchMethod(
- DexEncodedMethod emulatedDispatchMethod, DexType interfaceType) {
- MethodAccessFlags flags =
- MethodAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT | Constants.ACC_SYNTHETIC, false);
- DexMethod newMethod =
- appView
- .dexItemFactory()
- .createMethod(
- interfaceType,
- emulatedDispatchMethod.getProto(),
- emulatedDispatchMethod.getName());
- return new DexEncodedMethod(
- newMethod, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null, true);
- }
-
- private DexEncodedMethod generateHolderDispatchMethod(
- DexEncodedMethod emulatedDispatchMethod, DexType dispatchHolder, DexMethod itfMethod) {
- // The method should look like:
- // static foo(rcvr, arg0, arg1) {
- // if (rcvr instanceof interfaceType) {
- // return invoke-interface receiver.foo(arg0, arg1);
- // } else {
- // return DesugarX.foo(rcvr, arg0, arg1)
- // }
- // We do not deal with complex cases (multiple retargeting of the same signature in the
- // same inheritance tree, etc., since they do not happen in the most common desugared library.
- DexMethod desugarMethod =
- appView
- .options()
- .desugaredLibraryConfiguration
- .retargetMethod(emulatedDispatchMethod, appView);
- assert desugarMethod != null; // This method is reached only for retarget core lib members.
- DexMethod newMethod =
- appView
- .dexItemFactory()
- .createMethod(dispatchHolder, desugarMethod.proto, emulatedDispatchMethod.getName());
- return DexEncodedMethod.toEmulateDispatchLibraryMethod(
- emulatedDispatchMethod.getHolderType(),
- newMethod,
- desugarMethod,
- itfMethod,
- Collections.emptyList(),
- appView);
- }
- }
-
- private void reportInvalidLibrarySupertype(
- DexLibraryClass libraryClass, Set<DexEncodedMethod> retarget) {
- DexClass dexClass = appView.definitionFor(libraryClass.superType);
- String message;
- if (dexClass == null) {
- message = "missing";
- } else if (dexClass.isClasspathClass()) {
- message = "a classpath class";
- } else {
- message = "INVALID";
- assert false;
- }
- appView
- .options()
- .warningInvalidLibrarySuperclassForDesugar(
- dexClass == null ? libraryClass.getOrigin() : dexClass.getOrigin(),
- libraryClass.type,
- libraryClass.superType,
- message,
- retarget);
- }
-
- private DexType dispatchInterfaceTypeFor(DexEncodedMethod method) {
- return dispatchTypeFor(method, "dispatchInterface");
- }
-
- private DexType dispatchHolderTypeFor(DexEncodedMethod method) {
- return dispatchTypeFor(method, "dispatchHolder");
- }
-
- private DexType dispatchTypeFor(DexEncodedMethod method, String suffix) {
- String descriptor =
- "L"
- + appView
- .options()
- .desugaredLibraryConfiguration
- .getSynthesizedLibraryClassesPackagePrefix()
- + DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX
- + '$'
- + method.getHolderType().getName()
- + '$'
- + method.getName()
- + '$'
- + suffix
- + ';';
- return appView.dexItemFactory().createSynthesizedType(descriptor);
- }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java
index 4b9f409..6e300ba 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java
@@ -25,10 +25,6 @@
import java.util.concurrent.ConcurrentMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-<<<<<<< HEAD
-=======
-import org.junit.Assume;
->>>>>>> 6a837db0b... Desugared lib: Fix getGenericTypes
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;