Finalize LirToLirDesugaredLibraryRetargeter
This implements lir-to-lir rewriting of retargeted methods.
Bug: b/391572031
Change-Id: Ief64b512ad4d4e7438b1f16d2c0699571e95a012
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 909494b..693ff71 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -556,8 +556,8 @@
"Landroid/support/multidex/instrumentation/BuildConfig;",
"Landroid/test/runner/MultiDexTestRunner;");
- private List<DexType> createMultiDexTypes() {
- ImmutableList.Builder<DexType> builder = ImmutableList.builder();
+ private Set<DexType> createMultiDexTypes() {
+ ImmutableSet.Builder<DexType> builder = ImmutableSet.builder();
for (String prefix : MULTIDEX_PREFIXES) {
for (String suffix : MULTIDEX_SUFFIXES) {
builder.add(createType("L" + prefix + suffix));
@@ -569,7 +569,7 @@
return builder.build();
}
- public List<DexType> multiDexTypes = createMultiDexTypes();
+ public Set<DexType> multiDexTypes = createMultiDexTypes();
public final DexType doubleConsumer =
createStaticallyKnownType("Ljava/util/function/DoubleConsumer;");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java
index b3904bf..c7b54f2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java
@@ -99,7 +99,7 @@
LirToLirDesugaredLibraryLibRewriter desugaredLibraryLibRewriter =
DesugaredLibraryLibRewriter.createLirToLir(appView, eventConsumer);
LirToLirDesugaredLibraryRetargeter desugaredLibraryRetargeter =
- LirToLirDesugaredLibraryRetargeter.createLirToLir(appView);
+ LirToLirDesugaredLibraryRetargeter.createLirToLir(appView, eventConsumer);
// TODO(b/391572031): Implement lir-to-lir interface method rewriting.
InterfaceMethodRewriter interfaceMethodRewriter = null;
LirToLirDesugaredLibraryApiConverter desugaredLibraryAPIConverter =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/CfToCfDesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/CfToCfDesugaredLibraryRetargeter.java
index aed15b8..48a29d5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/CfToCfDesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/CfToCfDesugaredLibraryRetargeter.java
@@ -7,20 +7,14 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfOpcodeUtils;
-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.DexField;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
-import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.DesugarDescription;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
import java.util.Collections;
-import java.util.function.BiFunction;
import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
@@ -50,57 +44,40 @@
private DesugarDescription computeInvokeDescription(
CfInstruction instruction, ProgramMethod context) {
- if (appView.dexItemFactory().multiDexTypes.contains(context.getContextType())) {
+ if (!isApplicableToContext(context)) {
return DesugarDescription.nothing();
}
- CfInvoke cfInvoke = instruction.asInvoke();
- DexMethod invokedMethod = cfInvoke.getMethod();
- AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
- MethodResolutionResult resolutionResult =
- appInfo.resolveMethodLegacy(invokedMethod, cfInvoke.isInterface());
- if (!resolutionResult.isSingleResolution()) {
- return DesugarDescription.nothing();
- }
- assert resolutionResult.getSingleTarget() != null;
- DexMethod singleTarget = resolutionResult.getSingleTarget().getReference();
- if (cfInvoke.isInvokeStatic()) {
- DexMethod retarget = staticRetarget.get(singleTarget);
- return ensureInvokeRetargetingResult(retarget);
- }
- DesugarDescription retarget = computeNonStaticRetarget(singleTarget, false);
- if (!retarget.needsDesugaring()) {
- return DesugarDescription.nothing();
- }
- if (cfInvoke.isInvokeSuper(context.getHolderType())) {
- DexClassAndMethod superTarget =
- appInfo.lookupSuperTarget(invokedMethod, context, appView, appInfo);
- if (superTarget != null) {
- assert !superTarget.getDefinition().isStatic();
- return computeNonStaticRetarget(superTarget.getReference(), true);
- }
- }
- return retarget;
- }
-
- private DesugarDescription computeNonStaticRetarget(DexMethod singleTarget, boolean superInvoke) {
- EmulatedDispatchMethodDescriptor descriptor = emulatedVirtualRetarget.get(singleTarget);
- if (descriptor != null) {
- return createWithTarget(
- (eventConsumer, methodProcessingContext) ->
- superInvoke
- ? syntheticHelper.ensureForwardingMethod(descriptor, eventConsumer)
- : syntheticHelper.ensureEmulatedHolderDispatchMethod(descriptor, eventConsumer));
- }
- if (covariantRetarget.containsKey(singleTarget)) {
- return createWithTarget(
- (eventConsumer, methodProcessingContext) ->
- syntheticHelper.ensureCovariantRetargetMethod(
- singleTarget,
- covariantRetarget.get(singleTarget),
+ CfInvoke invoke = instruction.asInvoke();
+ DexMethod invokedMethod = invoke.getMethod();
+ InvokeType invokeType =
+ invoke.getInvokeType(
+ appView, context.getDefinition().getCode().getCodeLens(appView), context);
+ boolean isInterface = invoke.isInterface();
+ RetargetMethodSupplier retargetMethodSupplier =
+ getRetargetMethodSupplier(invokedMethod, invokeType, isInterface, context);
+ if (retargetMethodSupplier != null) {
+ return DesugarDescription.builder()
+ .setDesugarRewrite(
+ (position,
+ freshLocalProvider,
+ localStackAllocator,
+ desugaringInfo,
eventConsumer,
- methodProcessingContext));
+ innerContext,
+ methodProcessingContext,
+ desugarings,
+ dexItemFactory) -> {
+ DexMethod retargetMethod =
+ retargetMethodSupplier.getRetargetMethod(
+ eventConsumer, methodProcessingContext);
+ assert appView.definitionForHolder(retargetMethod, innerContext) != null;
+ assert !appView.definitionForHolder(retargetMethod, innerContext).isInterface();
+ return Collections.singletonList(
+ new CfInvoke(Opcodes.INVOKESTATIC, retargetMethod, false));
+ })
+ .build();
}
- return ensureInvokeRetargetingResult(nonEmulatedVirtualRetarget.get(singleTarget));
+ return null;
}
private DesugarDescription computeStaticFieldGetDescription(
@@ -124,37 +101,4 @@
Collections.singletonList(fieldInstruction.createWithField(retargetField)))
.build();
}
-
- DesugarDescription ensureInvokeRetargetingResult(DexMethod retarget) {
- if (retarget == null) {
- return DesugarDescription.nothing();
- }
- return createWithTarget(
- (eventConsumer, methodProcessingContext) ->
- syntheticHelper.ensureRetargetMethod(retarget, eventConsumer));
- }
-
- private DesugarDescription createWithTarget(
- BiFunction<CfInstructionDesugaringEventConsumer, MethodProcessingContext, DexMethod>
- methodProvider) {
- return DesugarDescription.builder()
- .setDesugarRewrite(
- (position,
- freshLocalProvider,
- localStackAllocator,
- desugaringInfo,
- eventConsumer,
- context,
- methodProcessingContext,
- desugarings,
- dexItemFactory) -> {
- DexMethod newInvokeTarget =
- methodProvider.apply(eventConsumer, methodProcessingContext);
- assert appView.definitionFor(newInvokeTarget.getHolderType()) != null;
- assert !appView.definitionFor(newInvokeTarget.getHolderType()).isInterface();
- return Collections.singletonList(
- new CfInvoke(Opcodes.INVOKESTATIC, newInvokeTarget, false));
- })
- .build();
- }
}
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 d340582..4c31664 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
@@ -3,19 +3,28 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter;
+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.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.desugaredlibrary.LibraryDesugaringOptions;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import java.util.Map;
+import java.util.Set;
public abstract class DesugaredLibraryRetargeter {
final AppView<?> appView;
+ private final Set<DexType> multiDexTypes;
final DesugaredLibraryRetargeterSyntheticHelper syntheticHelper;
private final Map<DexField, DexField> staticFieldRetarget;
@@ -26,6 +35,7 @@
public DesugaredLibraryRetargeter(AppView<?> appView) {
this.appView = appView;
+ this.multiDexTypes = appView.dexItemFactory().multiDexTypes;
this.syntheticHelper = new DesugaredLibraryRetargeterSyntheticHelper(appView);
MachineDesugaredLibrarySpecification specification =
appView.options().getLibraryDesugaringOptions().getMachineDesugaredLibrarySpecification();
@@ -46,16 +56,21 @@
return null;
}
- public static LirToLirDesugaredLibraryRetargeter createLirToLir(AppView<?> appView) {
+ public static LirToLirDesugaredLibraryRetargeter createLirToLir(
+ AppView<?> appView, CfInstructionDesugaringEventConsumer eventConsumer) {
LibraryDesugaringOptions libraryDesugaringOptions =
appView.options().getLibraryDesugaringOptions();
if (libraryDesugaringOptions.isLirToLirLibraryDesugaringEnabled()
&& libraryDesugaringOptions.getMachineDesugaredLibrarySpecification().hasRetargeting()) {
- return new LirToLirDesugaredLibraryRetargeter(appView);
+ return new LirToLirDesugaredLibraryRetargeter(appView, eventConsumer);
}
return null;
}
+ boolean isApplicableToContext(ProgramMethod context) {
+ return !multiDexTypes.contains(context.getHolderType());
+ }
+
DexField getRetargetField(DexField field, ProgramMethod context) {
DexEncodedField resolvedField =
appView.appInfoForDesugaring().resolveField(field, context).getResolvedField();
@@ -66,4 +81,65 @@
}
return null;
}
+
+ RetargetMethodSupplier getRetargetMethodSupplier(
+ DexMethod invokedMethod, InvokeType invokeType, boolean isInterface, ProgramMethod context) {
+ AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+ SingleResolutionResult<?> resolutionResult =
+ appInfo.resolveMethodLegacy(invokedMethod, isInterface).asSingleResolution();
+ if (resolutionResult == null) {
+ return null;
+ }
+ DexMethod resolvedMethod = resolutionResult.getResolvedMethod().getReference();
+ if (invokeType.isStatic()) {
+ return ensureRetargetMethod(resolvedMethod, staticRetarget);
+ }
+ RetargetMethodSupplier result = computeNonStaticRetarget(resolvedMethod, false);
+ if (result != null && invokeType.isSuper()) {
+ DexClassAndMethod singleTarget =
+ appInfo.lookupSuperTarget(invokedMethod, context, appView, appInfo);
+ if (singleTarget != null) {
+ assert !singleTarget.getDefinition().isStatic();
+ return computeNonStaticRetarget(singleTarget.getReference(), true);
+ }
+ }
+ return result;
+ }
+
+ private RetargetMethodSupplier computeNonStaticRetarget(
+ DexMethod singleTarget, boolean superInvoke) {
+ EmulatedDispatchMethodDescriptor descriptor = emulatedVirtualRetarget.get(singleTarget);
+ if (descriptor != null) {
+ return (eventConsumer, methodProcessingContext) ->
+ superInvoke
+ ? syntheticHelper.ensureForwardingMethod(descriptor, eventConsumer)
+ : syntheticHelper.ensureEmulatedHolderDispatchMethod(descriptor, eventConsumer);
+ }
+ if (covariantRetarget.containsKey(singleTarget)) {
+ return (eventConsumer, methodProcessingContext) ->
+ syntheticHelper.ensureCovariantRetargetMethod(
+ singleTarget,
+ covariantRetarget.get(singleTarget),
+ eventConsumer,
+ methodProcessingContext);
+ }
+ return ensureRetargetMethod(singleTarget, nonEmulatedVirtualRetarget);
+ }
+
+ private RetargetMethodSupplier ensureRetargetMethod(
+ DexMethod method, Map<DexMethod, DexMethod> retargetMap) {
+ DexMethod retargetMethod = retargetMap.get(method);
+ if (retargetMethod != null) {
+ return (eventConsumer, methodProcessingContext) ->
+ syntheticHelper.ensureRetargetMethod(retargetMethod, eventConsumer);
+ }
+ return null;
+ }
+
+ interface RetargetMethodSupplier {
+
+ DexMethod getRetargetMethod(
+ CfInstructionDesugaringEventConsumer eventConsumer,
+ MethodProcessingContext methodProcessingContext);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/LirToLirDesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/LirToLirDesugaredLibraryRetargeter.java
index 0d23fbb..5b689d5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/LirToLirDesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/LirToLirDesugaredLibraryRetargeter.java
@@ -6,15 +6,22 @@
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.lens.FieldLookupResult;
import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.desugaredlibrary.R8LibraryDesugaringGraphLens;
public class LirToLirDesugaredLibraryRetargeter extends DesugaredLibraryRetargeter {
- LirToLirDesugaredLibraryRetargeter(AppView<?> appView) {
+ private final CfInstructionDesugaringEventConsumer eventConsumer;
+
+ LirToLirDesugaredLibraryRetargeter(
+ AppView<?> appView, CfInstructionDesugaringEventConsumer eventConsumer) {
super(appView);
+ this.eventConsumer = eventConsumer;
}
public FieldLookupResult lookupField(
@@ -36,7 +43,24 @@
ProgramMethod context,
MethodProcessingContext methodProcessingContext,
R8LibraryDesugaringGraphLens lens) {
- // TODO(b/391572031): Implement.
+ if (isApplicableToContext(context)) {
+ RetargetMethodSupplier retargetMethodSupplier =
+ getRetargetMethodSupplier(
+ previous.getReference(),
+ previous.getType(),
+ previous.isInterface().toBoolean(),
+ context);
+ if (retargetMethodSupplier != null) {
+ DexMethod retargetMethod =
+ retargetMethodSupplier.getRetargetMethod(eventConsumer, methodProcessingContext);
+ return MethodLookupResult.builder(lens, lens.getPrevious())
+ .setReference(retargetMethod)
+ .setReboundReference(retargetMethod)
+ .setIsInterface(false)
+ .setType(InvokeType.STATIC)
+ .build();
+ }
+ }
return previous;
}
}