Move tracking of methods targeted by invoke-dynamic to keep info
Bug: 218986437
Change-Id: Idcb5121e4d5992a1d35f891d3ad783e0f91f1b68
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index d7dc429..78a8743 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -41,6 +41,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
/**
* The class merger is responsible for moving methods from the sources in {@link ClassMerger#group}
@@ -195,15 +196,22 @@
void mergeMethods(
SyntheticArgumentClass syntheticArgumentClass,
- SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder) {
- mergeVirtualMethods();
+ SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder,
+ Consumer<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfoConsumer) {
+ mergeVirtualMethods(virtuallyMergedMethodsKeepInfoConsumer);
mergeDirectMethods(syntheticArgumentClass, syntheticInitializerConverterBuilder);
classMethodsBuilder.setClassMethods(group.getTarget());
}
- void mergeVirtualMethods() {
+ void mergeVirtualMethods(
+ Consumer<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfoConsumer) {
virtualMethodMergers.forEach(
- merger -> merger.merge(classMethodsBuilder, lensBuilder, classIdentifiers));
+ merger ->
+ merger.merge(
+ classMethodsBuilder,
+ lensBuilder,
+ classIdentifiers,
+ virtuallyMergedMethodsKeepInfoConsumer));
group.forEachSource(clazz -> clazz.getMethodCollection().clearVirtualMethods());
}
@@ -318,13 +326,17 @@
public void mergeGroup(
PrunedItems.Builder prunedItemsBuilder,
SyntheticArgumentClass syntheticArgumentClass,
- SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder) {
+ SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder,
+ Consumer<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfoConsumer) {
fixAccessFlags();
fixNestMemberAttributes();
mergeAnnotations();
mergeInterfaces();
mergeFields(prunedItemsBuilder);
- mergeMethods(syntheticArgumentClass, syntheticInitializerConverterBuilder);
+ mergeMethods(
+ syntheticArgumentClass,
+ syntheticInitializerConverterBuilder,
+ virtuallyMergedMethodsKeepInfoConsumer);
group.getTarget().clearClassSignature();
group.getTarget().forEachProgramMember(ProgramMember::clearGenericSignature);
group.forEachSource(clazz -> prunedItemsBuilder.addRemovedClass(clazz.getType()));
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 18872a7..dd7de45 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -4,12 +4,18 @@
package com.android.tools.r8.horizontalclassmerging;
+import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
+
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.horizontalclassmerging.code.SyntheticInitializerConverter;
+import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.shaking.KeepInfoCollection;
@@ -24,6 +30,7 @@
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
public class HorizontalClassMerger {
@@ -104,9 +111,13 @@
: null;
SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder =
SyntheticInitializerConverter.builder(appView, codeProvider);
+ List<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfos = new ArrayList<>();
PrunedItems prunedItems =
applyClassMergers(
- classMergers, syntheticArgumentClass, syntheticInitializerConverterBuilder);
+ classMergers,
+ syntheticArgumentClass,
+ syntheticInitializerConverterBuilder,
+ virtuallyMergedMethodsKeepInfos::add);
SyntheticInitializerConverter syntheticInitializerConverter =
syntheticInitializerConverterBuilder.build();
@@ -144,6 +155,37 @@
appView.pruneItems(
prunedItems.toBuilder().setPrunedApp(appView.app()).build(), executorService);
+
+ amendKeepInfo(horizontalClassMergerGraphLens, virtuallyMergedMethodsKeepInfos);
+ }
+
+ private void amendKeepInfo(
+ HorizontalClassMergerGraphLens horizontalClassMergerGraphLens,
+ List<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfos) {
+ appView
+ .getKeepInfo()
+ .mutate(
+ keepInfo -> {
+ for (VirtuallyMergedMethodsKeepInfo virtuallyMergedMethodsKeepInfo :
+ virtuallyMergedMethodsKeepInfos) {
+ DexMethod representative = virtuallyMergedMethodsKeepInfo.getRepresentative();
+ MethodLookupResult lookupResult =
+ horizontalClassMergerGraphLens.lookupMethod(
+ representative,
+ null,
+ Type.VIRTUAL,
+ horizontalClassMergerGraphLens.getPrevious());
+ ProgramMethod mergedMethod =
+ asProgramMethodOrNull(appView.definitionFor(lookupResult.getReference()));
+ if (mergedMethod != null) {
+ keepInfo.joinMethod(
+ mergedMethod,
+ info -> info.merge(virtuallyMergedMethodsKeepInfo.getKeepInfo()));
+ continue;
+ }
+ assert false;
+ }
+ });
}
private FieldAccessInfoCollectionModifier createFieldAccessInfoCollectionModifier(
@@ -245,11 +287,15 @@
private PrunedItems applyClassMergers(
Collection<ClassMerger> classMergers,
SyntheticArgumentClass syntheticArgumentClass,
- SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder) {
+ SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder,
+ Consumer<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfoConsumer) {
PrunedItems.Builder prunedItemsBuilder = PrunedItems.builder().setPrunedApp(appView.app());
for (ClassMerger merger : classMergers) {
merger.mergeGroup(
- prunedItemsBuilder, syntheticArgumentClass, syntheticInitializerConverterBuilder);
+ prunedItemsBuilder,
+ syntheticArgumentClass,
+ syntheticInitializerConverterBuilder,
+ virtuallyMergedMethodsKeepInfoConsumer);
}
return prunedItemsBuilder.build();
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index 07d1fd0..67cc625 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -23,6 +23,7 @@
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
public class VirtualMethodMerger {
@@ -224,7 +225,8 @@
public void merge(
ClassMethodsBuilder classMethodsBuilder,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- Reference2IntMap<DexType> classIdentifiers) {
+ Reference2IntMap<DexType> classIdentifiers,
+ Consumer<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfoConsumer) {
assert !methods.isEmpty();
// Handle trivial merges.
@@ -284,13 +286,20 @@
}
// Map each old non-abstract method to the newly synthesized method in the graph lens.
+ VirtuallyMergedMethodsKeepInfo virtuallyMergedMethodsKeepInfo =
+ new VirtuallyMergedMethodsKeepInfo(representative.getReference());
for (ProgramMethod oldMethod : methods) {
lensBuilder.mapMethod(oldMethod.getReference(), newMethodReference);
+ virtuallyMergedMethodsKeepInfo.amendKeepInfo(appView.getKeepInfo(oldMethod));
}
// Add a mapping from a synthetic name to the synthetic merged method.
lensBuilder.recordNewMethodSignature(bridgeMethodReference, newMethodReference);
classMethodsBuilder.addVirtualMethod(newMethod);
+
+ if (!virtuallyMergedMethodsKeepInfo.getKeepInfo().isBottom()) {
+ virtuallyMergedMethodsKeepInfoConsumer.accept(virtuallyMergedMethodsKeepInfo);
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtuallyMergedMethodsKeepInfo.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtuallyMergedMethodsKeepInfo.java
new file mode 100644
index 0000000..b395d5d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtuallyMergedMethodsKeepInfo.java
@@ -0,0 +1,31 @@
+// 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.horizontalclassmerging;
+
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.shaking.KeepMethodInfo;
+import com.android.tools.r8.shaking.KeepMethodInfo.Joiner;
+
+public class VirtuallyMergedMethodsKeepInfo {
+
+ private final DexMethod representative;
+ private final KeepMethodInfo.Joiner keepInfo = KeepMethodInfo.newEmptyJoiner();
+
+ public VirtuallyMergedMethodsKeepInfo(DexMethod representative) {
+ this.representative = representative;
+ }
+
+ public void amendKeepInfo(KeepMethodInfo keepInfo) {
+ this.keepInfo.merge(keepInfo.joiner());
+ }
+
+ public DexMethod getRepresentative() {
+ return representative;
+ }
+
+ public Joiner getKeepInfo() {
+ return keepInfo;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java
index a46a6bc..125b53c 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CallSiteInformation.java
@@ -8,6 +8,8 @@
import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.KeepMethodInfo;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.classhierarchy.MethodOverridesCollector;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.Sets;
@@ -57,14 +59,17 @@
private final Set<DexMethod> multiCallerInlineCandidates = Sets.newIdentityHashSet();
CallGraphBasedCallSiteInformation(AppView<AppInfoWithLiveness> appView, CallGraph graph) {
+ InternalOptions options = appView.options();
ProgramMethodSet pinned =
MethodOverridesCollector.findAllMethodsAndOverridesThatMatches(
appView,
ImmediateProgramSubtypingInfo.create(appView),
appView.appInfo().classes(),
- method ->
- appView.getKeepInfo(method).isPinned(appView.options())
- || appView.appInfo().isMethodTargetedByInvokeDynamic(method));
+ method -> {
+ KeepMethodInfo keepInfo = appView.getKeepInfo(method);
+ return !keepInfo.isClosedWorldReasoningAllowed(options)
+ || keepInfo.isPinned(options);
+ });
for (Node node : graph.getNodes()) {
ProgramMethod method = node.getProgramMethod();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java b/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java
deleted file mode 100644
index 8f9421d..0000000
--- a/src/main/java/com/android/tools/r8/ir/optimize/ArgumentRemovalUtils.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.ir.optimize;
-
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-
-public class ArgumentRemovalUtils {
-
- // Returns true if this method is pinned from the perspective of optimizations that attempt to
- // remove method arguments.
- public static boolean isPinned(DexEncodedMethod method, AppView<AppInfoWithLiveness> appView) {
- return appView.appInfo().isPinned(method.getReference())
- || appView.appInfo().isBootstrapMethod(method.getReference())
- || appView.appInfo().isFailedResolutionTarget(method.getReference())
- || appView.appInfo().isMethodTargetedByInvokeDynamic(method.getReference())
- || method.accessFlags.isNative();
- }
-}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
index 5517455..24d6e46 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -420,7 +420,6 @@
return appView.getKeepInfo(method).isParameterRemovalAllowed(options)
&& !method.getDefinition().isLibraryMethodOverride().isPossiblyTrue()
&& !appView.appInfo().isBootstrapMethod(method)
- && !appView.appInfo().isMethodTargetedByInvokeDynamic(method)
&& !interfaceDispatchOutsideProgram.contains(method);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java
index c277bb7..28aa563 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorUnoptimizableMethods.java
@@ -67,7 +67,6 @@
AppInfoWithLiveness appInfo = appView.appInfo();
InternalOptions options = appView.options();
return method.getDefinition().isLibraryMethodOverride().isPossiblyTrue()
- || appInfo.isMethodTargetedByInvokeDynamic(method)
|| !appInfo.getKeepInfo().getMethodInfo(method).isArgumentPropagationAllowed(options);
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/utils/ParameterRemovalUtils.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/utils/ParameterRemovalUtils.java
index 34d8967..cb44578 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/utils/ParameterRemovalUtils.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/utils/ParameterRemovalUtils.java
@@ -22,8 +22,7 @@
if (!appView.getKeepInfo(method).isUnusedArgumentOptimizationAllowed(options)) {
return false;
}
- return method.getDefinition().isLibraryMethodOverride().isFalse()
- && !appView.appInfoWithLiveness().isMethodTargetedByInvokeDynamic(method);
+ return method.getDefinition().isLibraryMethodOverride().isFalse();
}
public static boolean canRemoveUnusedParameter(
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 8216777..7464171 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -112,8 +112,6 @@
*/
private final Set<DexMethod> bootstrapMethods;
- /** Set of methods that are the immediate target of an invoke-dynamic. */
- private final Set<DexMethod> methodsTargetedByInvokeDynamic;
/** Set of virtual methods that are the immediate target of an invoke-direct. */
private final Set<DexMethod> virtualMethodsTargetedByInvokeDirect;
/**
@@ -210,7 +208,6 @@
Set<DexMethod> failedMethodResolutionTargets,
Set<DexField> failedFieldResolutionTargets,
Set<DexMethod> bootstrapMethods,
- Set<DexMethod> methodsTargetedByInvokeDynamic,
Set<DexMethod> virtualMethodsTargetedByInvokeDirect,
Set<DexMethod> liveMethods,
FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
@@ -245,7 +242,6 @@
this.failedMethodResolutionTargets = failedMethodResolutionTargets;
this.failedFieldResolutionTargets = failedFieldResolutionTargets;
this.bootstrapMethods = bootstrapMethods;
- this.methodsTargetedByInvokeDynamic = methodsTargetedByInvokeDynamic;
this.virtualMethodsTargetedByInvokeDirect = virtualMethodsTargetedByInvokeDirect;
this.liveMethods = liveMethods;
this.fieldAccessInfoCollection = fieldAccessInfoCollection;
@@ -288,7 +284,6 @@
previous.failedMethodResolutionTargets,
previous.failedFieldResolutionTargets,
previous.bootstrapMethods,
- previous.methodsTargetedByInvokeDynamic,
previous.virtualMethodsTargetedByInvokeDirect,
previous.liveMethods,
previous.fieldAccessInfoCollection,
@@ -335,8 +330,6 @@
pruneFields(previous.failedFieldResolutionTargets, prunedItems, executorService, futures),
pruneMethods(previous.bootstrapMethods, prunedItems, executorService, futures),
pruneMethods(
- previous.methodsTargetedByInvokeDynamic, prunedItems, executorService, futures),
- pruneMethods(
previous.virtualMethodsTargetedByInvokeDirect, prunedItems, executorService, futures),
pruneMethods(previous.liveMethods, prunedItems, executorService, futures),
previous.fieldAccessInfoCollection,
@@ -541,7 +534,6 @@
failedMethodResolutionTargets,
failedFieldResolutionTargets,
bootstrapMethods,
- methodsTargetedByInvokeDynamic,
virtualMethodsTargetedByInvokeDirect,
liveMethods,
fieldAccessInfoCollection,
@@ -621,7 +613,6 @@
this.failedMethodResolutionTargets = previous.failedMethodResolutionTargets;
this.failedFieldResolutionTargets = previous.failedFieldResolutionTargets;
this.bootstrapMethods = previous.bootstrapMethods;
- this.methodsTargetedByInvokeDynamic = previous.methodsTargetedByInvokeDynamic;
this.virtualMethodsTargetedByInvokeDirect = previous.virtualMethodsTargetedByInvokeDirect;
this.liveMethods = previous.liveMethods;
this.fieldAccessInfoCollection = previous.fieldAccessInfoCollection;
@@ -745,14 +736,6 @@
return isBootstrapMethod(method.getReference());
}
- public boolean isMethodTargetedByInvokeDynamic(DexMethod method) {
- return methodsTargetedByInvokeDynamic.contains(method);
- }
-
- public boolean isMethodTargetedByInvokeDynamic(ProgramMethod method) {
- return isMethodTargetedByInvokeDynamic(method.getReference());
- }
-
public Set<DexMethod> getVirtualMethodsTargetedByInvokeDirect() {
return virtualMethodsTargetedByInvokeDirect;
}
@@ -1232,7 +1215,6 @@
lens.rewriteReferences(failedMethodResolutionTargets),
lens.rewriteReferences(failedFieldResolutionTargets),
lens.rewriteReferences(bootstrapMethods),
- lens.rewriteReferences(methodsTargetedByInvokeDynamic),
lens.rewriteReferences(virtualMethodsTargetedByInvokeDirect),
lens.rewriteReferences(liveMethods),
fieldAccessInfoCollection.rewrittenWithLens(definitionSupplier, lens),
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 941e354..1125b65 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -355,10 +355,6 @@
*/
private final Set<DexMethod> bootstrapMethods = Sets.newIdentityHashSet();
/**
- * Set of direct methods that are the immediate target of an invoke-dynamic.
- */
- private final Set<DexMethod> methodsTargetedByInvokeDynamic = Sets.newIdentityHashSet();
- /**
* Set of virtual methods that are the immediate target of an invoke-direct.
*/
private final Set<DexMethod> virtualMethodsTargetedByInvokeDirect = Sets.newIdentityHashSet();
@@ -1030,7 +1026,7 @@
if (bootstrapArgument.isDexValueMethodHandle()) {
DexMethodHandle method = bootstrapArgument.asDexValueMethodHandle().getValue();
if (method.isMethodHandle()) {
- methodsTargetedByInvokeDynamic.add(method.asMethod());
+ disableClosedWorldReasoning(method.asMethod(), context);
}
}
}
@@ -1051,10 +1047,6 @@
assert implHandle != null;
DexMethod method = implHandle.asMethod();
- if (!methodsTargetedByInvokeDynamic.add(method)) {
- return;
- }
-
switch (implHandle.type) {
case INVOKE_STATIC:
traceInvokeStaticFromLambda(method, context);
@@ -1074,6 +1066,18 @@
default:
throw new Unreachable();
}
+
+ disableClosedWorldReasoning(method, context);
+ }
+
+ private void disableClosedWorldReasoning(DexMethod reference, ProgramMethod context) {
+ SingleResolutionResult resolutionResult =
+ resolveMethod(reference, context, KeepReason.methodHandleReferencedIn(context));
+ if (resolutionResult != null && resolutionResult.getResolvedHolder().isProgramClass()) {
+ applyMinimumKeepInfoWhenLiveOrTargeted(
+ resolutionResult.getResolvedProgramMethod(),
+ KeepMethodInfo.newEmptyJoiner().disallowClosedWorldReasoning());
+ }
}
void traceCheckCast(DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
@@ -3839,7 +3843,6 @@
failedMethodResolutionTargets,
failedFieldResolutionTargets,
bootstrapMethods,
- methodsTargetedByInvokeDynamic,
virtualMethodsTargetedByInvokeDirect,
toDescriptorSet(liveMethods.getItems()),
// Filter out library fields and pinned fields, because these are read by default.
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java
index cd46a71..0173fb2 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java
@@ -25,6 +25,7 @@
}
private final boolean allowClassInlining;
+ private final boolean allowClosedWorldReasoning;
private final boolean allowConstantArgumentOptimization;
private final boolean allowInlining;
private final boolean allowMethodStaticizing;
@@ -37,6 +38,7 @@
private KeepMethodInfo(Builder builder) {
super(builder);
this.allowClassInlining = builder.isClassInliningAllowed();
+ this.allowClosedWorldReasoning = builder.isClosedWorldReasoningAllowed();
this.allowConstantArgumentOptimization = builder.isConstantArgumentOptimizationAllowed();
this.allowInlining = builder.isInliningAllowed();
this.allowMethodStaticizing = builder.isMethodStaticizingAllowed();
@@ -59,7 +61,8 @@
}
public boolean isParameterRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& !isCheckDiscardedEnabled(configuration);
}
@@ -72,6 +75,14 @@
return allowClassInlining;
}
+ public boolean isClosedWorldReasoningAllowed(GlobalKeepInfoConfiguration configuration) {
+ return isOptimizationAllowed(configuration) && internalIsClosedWorldReasoningAllowed();
+ }
+
+ boolean internalIsClosedWorldReasoningAllowed() {
+ return allowClosedWorldReasoning;
+ }
+
public boolean isConstantArgumentOptimizationAllowed(GlobalKeepInfoConfiguration configuration) {
return isOptimizationAllowed(configuration) && internalIsConstantArgumentOptimizationAllowed();
}
@@ -89,7 +100,8 @@
}
public boolean isMethodStaticizingAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& configuration.isMethodStaticizingEnabled()
&& internalIsMethodStaticizingAllowed();
@@ -100,7 +112,8 @@
}
public boolean isParameterReorderingAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsParameterReorderingAllowed();
}
@@ -110,7 +123,8 @@
}
public boolean isParameterTypeStrengtheningAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsParameterTypeStrengtheningAllowed();
}
@@ -120,7 +134,8 @@
}
public boolean isReturnTypeStrengtheningAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsReturnTypeStrengtheningAllowed();
}
@@ -130,7 +145,8 @@
}
public boolean isUnusedArgumentOptimizationAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsUnusedArgumentOptimizationAllowed();
}
@@ -140,7 +156,8 @@
}
public boolean isUnusedReturnValueOptimizationAllowed(GlobalKeepInfoConfiguration configuration) {
- return isOptimizationAllowed(configuration)
+ return isClosedWorldReasoningAllowed(configuration)
+ && isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsUnusedReturnValueOptimizationAllowed();
}
@@ -167,6 +184,7 @@
public static class Builder extends KeepInfo.Builder<Builder, KeepMethodInfo> {
private boolean allowClassInlining;
+ private boolean allowClosedWorldReasoning;
private boolean allowConstantArgumentOptimization;
private boolean allowInlining;
private boolean allowMethodStaticizing;
@@ -183,6 +201,7 @@
private Builder(KeepMethodInfo original) {
super(original);
allowClassInlining = original.internalIsClassInliningAllowed();
+ allowClosedWorldReasoning = original.internalIsClosedWorldReasoningAllowed();
allowConstantArgumentOptimization = original.internalIsConstantArgumentOptimizationAllowed();
allowInlining = original.internalIsInliningAllowed();
allowMethodStaticizing = original.internalIsMethodStaticizingAllowed();
@@ -213,6 +232,25 @@
return setAllowClassInlining(false);
}
+ // Closed world reasoning.
+
+ public boolean isClosedWorldReasoningAllowed() {
+ return allowClosedWorldReasoning;
+ }
+
+ public Builder setAllowClosedWorldReasoning(boolean allowClosedWorldReasoning) {
+ this.allowClosedWorldReasoning = allowClosedWorldReasoning;
+ return self();
+ }
+
+ public Builder allowClosedWorldReasoning() {
+ return setAllowClosedWorldReasoning(true);
+ }
+
+ public Builder disallowClosedWorldReasoning() {
+ return setAllowClosedWorldReasoning(false);
+ }
+
// Constant argument optimization.
public boolean isConstantArgumentOptimizationAllowed() {
@@ -390,6 +428,7 @@
boolean internalIsEqualTo(KeepMethodInfo other) {
return super.internalIsEqualTo(other)
&& isClassInliningAllowed() == other.internalIsClassInliningAllowed()
+ && isClosedWorldReasoningAllowed() == other.internalIsClosedWorldReasoningAllowed()
&& isConstantArgumentOptimizationAllowed()
== other.internalIsConstantArgumentOptimizationAllowed()
&& isInliningAllowed() == other.internalIsInliningAllowed()
@@ -413,6 +452,7 @@
public Builder makeTop() {
return super.makeTop()
.disallowClassInlining()
+ .disallowClosedWorldReasoning()
.disallowConstantArgumentOptimization()
.disallowInlining()
.disallowMethodStaticizing()
@@ -427,6 +467,7 @@
public Builder makeBottom() {
return super.makeBottom()
.allowClassInlining()
+ .allowClosedWorldReasoning()
.allowConstantArgumentOptimization()
.allowInlining()
.allowMethodStaticizing()
@@ -449,6 +490,11 @@
return self();
}
+ public Joiner disallowClosedWorldReasoning() {
+ builder.disallowClosedWorldReasoning();
+ return self();
+ }
+
public Joiner disallowConstantArgumentOptimization() {
builder.disallowConstantArgumentOptimization();
return self();
@@ -500,6 +546,8 @@
return super.merge(joiner)
.applyIf(!joiner.builder.isClassInliningAllowed(), Joiner::disallowClassInlining)
.applyIf(
+ !joiner.builder.isClosedWorldReasoningAllowed(), Joiner::disallowClosedWorldReasoning)
+ .applyIf(
!joiner.builder.isConstantArgumentOptimizationAllowed(),
Joiner::disallowConstantArgumentOptimization)
.applyIf(!joiner.builder.isInliningAllowed(), Joiner::disallowInlining)