Adapt and simplify RetargetingInfo
Bug: 184026720
Change-Id: Ic283f0b2ad217097a0985c870c8c64f277f47d4d
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 c4a01f6..950459f 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
@@ -9,13 +9,13 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
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.DexProto;
-import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
@@ -28,7 +28,6 @@
import com.android.tools.r8.utils.collections.DexClassAndMethodSet;
import java.util.Collection;
import java.util.Collections;
-import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -40,22 +39,23 @@
private final DesugaredLibraryRetargeterSyntheticHelper syntheticHelper;
private final RetargetingInfo retargetingInfo;
- private final Map<DexMethod, DexMethod> retargetLibraryMember;
- private final Map<DexString, List<DexMethod>> nonFinalHolderRewrites;
+ private final Map<DexMethod, DexMethod> staticRetarget;
+ private final Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget;
private final DexClassAndMethodSet emulatedDispatchMethods;
public DesugaredLibraryRetargeter(AppView<?> appView) {
this.appView = appView;
this.syntheticHelper = new DesugaredLibraryRetargeterSyntheticHelper(appView);
retargetingInfo = RetargetingInfo.get(appView);
- retargetLibraryMember = retargetingInfo.getRetargetLibraryMember();
- nonFinalHolderRewrites = retargetingInfo.getNonFinalHolderRewrites();
+ staticRetarget = retargetingInfo.getStaticRetarget();
+ nonEmulatedVirtualRetarget = retargetingInfo.getNonEmulatedVirtualRetarget();
emulatedDispatchMethods = retargetingInfo.getEmulatedDispatchMethods();
}
// Used by the ListOfBackportedMethods utility.
public void visit(Consumer<DexMethod> consumer) {
- retargetLibraryMember.keySet().forEach(consumer);
+ staticRetarget.keySet().forEach(consumer);
+ nonEmulatedVirtualRetarget.keySet().forEach(consumer);
}
public RetargetingInfo getRetargetingInfo() {
@@ -125,7 +125,7 @@
private InvokeRetargetingResult computeNewInvokeTarget(
CfInstruction instruction, ProgramMethod context) {
- if (retargetLibraryMember.isEmpty() || !instruction.isInvoke()) {
+ if (!instruction.isInvoke()) {
return NO_REWRITING;
}
if (appView
@@ -137,17 +137,27 @@
}
CfInvoke cfInvoke = instruction.asInvoke();
DexMethod invokedMethod = cfInvoke.getMethod();
- InvokeRetargetingResult retarget =
- computeRetargetedMethod(invokedMethod, cfInvoke.isInterface());
+ AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+ MethodResolutionResult resolutionResult =
+ appInfo.resolveMethod(invokedMethod, cfInvoke.isInterface());
+ if (!resolutionResult.isSingleResolution()) {
+ return NO_REWRITING;
+ }
+ DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
+ assert singleTarget != null;
+ if (cfInvoke.isInvokeStatic()) {
+ DexMethod retarget = staticRetarget.get(singleTarget.getReference());
+ return retarget == null
+ ? NO_REWRITING
+ : InvokeRetargetingResult.createInvokeRetargetingResult(retarget);
+ }
+ InvokeRetargetingResult retarget = computeNonStaticRetarget(singleTarget);
if (!retarget.hasNewInvokeTarget()) {
return NO_REWRITING;
}
- if (cfInvoke.isInvokeSuper(context.getHolderType())
- && matchesNonFinalHolderRewrite(invokedMethod)) {
- DexClassAndMethod superTarget =
- appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, context);
- // Final methods can be rewritten as a normal invoke.
- if (superTarget != null && !superTarget.getAccessFlags().isFinal()) {
+ if (cfInvoke.isInvokeSuper(context.getHolderType())) {
+ DexClassAndMethod superTarget = appInfo.lookupSuperTarget(invokedMethod, context);
+ if (superTarget != null) {
return InvokeRetargetingResult.createInvokeRetargetingResult(
appView.options().desugaredLibrarySpecification.retargetMethod(superTarget, appView));
}
@@ -155,59 +165,23 @@
return retarget;
}
- private InvokeRetargetingResult computeRetargetedMethod(
- DexMethod invokedMethod, boolean isInterface) {
- InvokeRetargetingResult invokeRetargetingResult = computeRetargetLibraryMember(invokedMethod);
- if (!invokeRetargetingResult.hasNewInvokeTarget()) {
- if (!matchesNonFinalHolderRewrite(invokedMethod)) {
- return NO_REWRITING;
- }
- // We need to force resolution, even on d8, to know if the invoke has to be rewritten.
- MethodResolutionResult resolutionResult =
- appView.appInfoForDesugaring().resolveMethod(invokedMethod, isInterface);
- if (resolutionResult.isFailedResolution()) {
- return NO_REWRITING;
- }
- DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
- assert singleTarget != null;
- invokeRetargetingResult = computeRetargetLibraryMember(singleTarget.getReference());
- }
- return invokeRetargetingResult;
- }
-
- private InvokeRetargetingResult computeRetargetLibraryMember(DexMethod method) {
- DexClassAndMethod emulatedMethod = emulatedDispatchMethods.get(method);
+ private InvokeRetargetingResult computeNonStaticRetarget(DexEncodedMethod singleTarget) {
+ assert !singleTarget.isStatic();
+ DexMethod reference = singleTarget.getReference();
+ DexClassAndMethod emulatedMethod = emulatedDispatchMethods.get(reference);
if (emulatedMethod != null) {
- assert !emulatedMethod.getAccessFlags().isStatic();
return new InvokeRetargetingResult(
true,
eventConsumer -> {
DexType newHolder =
syntheticHelper.ensureEmulatedHolderDispatchMethod(emulatedMethod, eventConsumer)
.type;
- return computeRetargetMethod(
- method, emulatedMethod.getAccessFlags().isStatic(), newHolder);
+ DexItemFactory factory = appView.dexItemFactory();
+ DexProto newProto = factory.prependHolderToProto(reference);
+ return factory.createMethod(newHolder, newProto, reference.getName());
});
}
- return InvokeRetargetingResult.createInvokeRetargetingResult(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;
- }
-
- 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());
+ return InvokeRetargetingResult.createInvokeRetargetingResult(
+ nonEmulatedVirtualRetarget.get(reference));
}
}
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 d9656fe..79c2b3a 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
@@ -22,20 +22,18 @@
public class RetargetingInfo {
- private final Map<DexMethod, DexMethod> retargetLibraryMember;
- // 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;
+ private final Map<DexMethod, DexMethod> staticRetarget;
+ private final Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget;
+
// Non final virtual library methods requiring generation of emulated dispatch.
private final DexClassAndMethodSet emulatedDispatchMethods;
RetargetingInfo(
- Map<DexMethod, DexMethod> retargetLibraryMember,
- Map<DexString, List<DexMethod>> nonFinalHolderRewrites,
+ Map<DexMethod, DexMethod> staticRetarget,
+ Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget,
DexClassAndMethodSet emulatedDispatchMethods) {
- this.retargetLibraryMember = retargetLibraryMember;
- this.nonFinalHolderRewrites = nonFinalHolderRewrites;
+ this.staticRetarget = staticRetarget;
+ this.nonEmulatedVirtualRetarget = nonEmulatedVirtualRetarget;
this.emulatedDispatchMethods = emulatedDispatchMethods;
}
@@ -43,12 +41,12 @@
return new RetargetingInfoBuilder(appView).computeRetargetingInfo();
}
- public Map<DexMethod, DexMethod> getRetargetLibraryMember() {
- return retargetLibraryMember;
+ public Map<DexMethod, DexMethod> getStaticRetarget() {
+ return staticRetarget;
}
- public Map<DexString, List<DexMethod>> getNonFinalHolderRewrites() {
- return nonFinalHolderRewrites;
+ public Map<DexMethod, DexMethod> getNonEmulatedVirtualRetarget() {
+ return nonEmulatedVirtualRetarget;
}
public DexClassAndMethodSet getEmulatedDispatchMethods() {
@@ -58,8 +56,8 @@
private static class RetargetingInfoBuilder {
private final AppView<?> appView;
- private final Map<DexMethod, DexMethod> retargetLibraryMember = new IdentityHashMap<>();
- private final Map<DexString, List<DexMethod>> nonFinalHolderRewrites = new IdentityHashMap<>();
+ private final Map<DexMethod, DexMethod> staticRetarget = new IdentityHashMap<>();
+ private final Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget = new IdentityHashMap<>();
private final DexClassAndMethodSet emulatedDispatchMethods = DexClassAndMethodSet.create();
public RetargetingInfoBuilder(AppView<?> appView) {
@@ -82,28 +80,26 @@
DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
List<DexClassAndMethod> found = findMethodsWithName(methodName, typeClass);
for (DexClassAndMethod method : found) {
- boolean emulatedDispatch = false;
DexMethod methodReference = method.getReference();
- if (!typeClass.isFinal()) {
- nonFinalHolderRewrites.putIfAbsent(method.getName(), new ArrayList<>());
- nonFinalHolderRewrites.get(method.getName()).add(methodReference);
- if (!method.getAccessFlags().isStatic()) {
- if (isEmulatedInterfaceDispatch(method)) {
- // In this case interface method rewriter takes care of it.
- continue;
- } else if (!method.getAccessFlags().isFinal()) {
- // Virtual rewrites require emulated dispatch for inheritance.
- // The call is rewritten to the dispatch holder class instead.
- emulatedDispatchMethods.add(method);
- emulatedDispatch = true;
- }
- }
- }
- if (!emulatedDispatch) {
- retargetLibraryMember.put(
+ 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.
+ emulatedDispatchMethods.add(method);
}
}
}
@@ -123,7 +119,7 @@
DexMethod target =
computeRetargetMethod(
source, true, itemFactory.createType("Ljava/util/DesugarArrays;"));
- retargetLibraryMember.put(source, target);
+ 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");
@@ -136,11 +132,11 @@
target =
computeRetargetMethod(
source, true, itemFactory.createType("Ljava/util/DesugarTimeZone;"));
- retargetLibraryMember.put(source, target);
+ staticRetarget.put(source, target);
}
return new RetargetingInfo(
- ImmutableMap.copyOf(retargetLibraryMember),
- ImmutableMap.copyOf(nonFinalHolderRewrites),
+ ImmutableMap.copyOf(staticRetarget),
+ ImmutableMap.copyOf(nonEmulatedVirtualRetarget),
emulatedDispatchMethods);
}