Introduce a collection of optimization info for resolution results
Change-Id: I72a7a7c196e199d77f813ecc2644e48159986cee
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 30bbe20..4a8b427 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -31,6 +31,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValueJoiner.AbstractValueParameterJoiner;
import com.android.tools.r8.ir.desugar.TypeRewriter;
import com.android.tools.r8.ir.optimize.enums.EnumDataMap;
+import com.android.tools.r8.ir.optimize.info.MethodResolutionOptimizationInfoCollection;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoFactory;
import com.android.tools.r8.ir.optimize.library.LibraryMemberOptimizer;
import com.android.tools.r8.ir.optimize.library.LibraryMethodSideEffectModelCollection;
@@ -95,6 +96,8 @@
private NamingLens namingLens = NamingLens.getIdentityLens();
private ProguardCompatibilityActions proguardCompatibilityActions;
private RootSet rootSet;
+ private MethodResolutionOptimizationInfoCollection methodResolutionOptimizationInfoCollection =
+ MethodResolutionOptimizationInfoCollection.empty();
private MainDexRootSet mainDexRootSet = null;
private StartupProfile startupProfile;
@@ -340,6 +343,16 @@
return abstractValueParameterJoiner;
}
+ public MethodResolutionOptimizationInfoCollection
+ getMethodResolutionOptimizationInfoCollection() {
+ return methodResolutionOptimizationInfoCollection;
+ }
+
+ public void setMethodResolutionOptimizationInfoCollection(
+ MethodResolutionOptimizationInfoCollection getMethodResolutionOptimizationInfoCollection) {
+ this.methodResolutionOptimizationInfoCollection = getMethodResolutionOptimizationInfoCollection;
+ }
+
public InstanceFieldInitializationInfoFactory instanceFieldInitializationInfoFactory() {
return instanceFieldInitializationInfoFactory;
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index d7362d6..428c57d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -8,7 +8,11 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
import com.android.tools.r8.graph.LookupResult.LookupResultSuccess.LookupResultCollectionState;
+import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
+import com.android.tools.r8.ir.optimize.info.DefaultMethodOptimizationInfo;
+import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
+import com.android.tools.r8.ir.optimize.info.MethodResolutionOptimizationInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.InstantiatedObject;
import com.android.tools.r8.utils.BooleanBox;
@@ -283,6 +287,19 @@
public abstract SingleResolutionResult<T> withInitialResolutionHolder(
DexClass newInitialResolutionHolder);
+ public MethodOptimizationInfo getOptimizationInfo(
+ AppView<?> appView, InvokeMethod invoke, DexClassAndMethod singleTarget) {
+ if (singleTarget != null) {
+ return singleTarget.getOptimizationInfo();
+ }
+ if (invoke.isInvokeMethodWithDynamicDispatch() && resolvedMethod.belongsToVirtualPool()) {
+ MethodResolutionOptimizationInfoCollection methodResolutionOptimizationInfoCollection =
+ appView.getMethodResolutionOptimizationInfoCollection();
+ return methodResolutionOptimizationInfoCollection.get(resolvedMethod, resolvedHolder);
+ }
+ return DefaultMethodOptimizationInfo.getInstance();
+ }
+
@Override
public DexClass getInitialResolutionHolder() {
return initialResolutionHolder;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java
index 0680915..21abec1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java
@@ -250,12 +250,13 @@
}
}
- if (singleTarget == null) {
+ MethodOptimizationInfo optimizationInfo =
+ resolutionResult.getOptimizationInfo(appView, invoke, singleTarget);
+ if (optimizationInfo.isDefault()) {
return false;
}
boolean needsAssumeInstruction = false;
- MethodOptimizationInfo optimizationInfo = singleTarget.getDefinition().getOptimizationInfo();
// Case (2), invocations that are guaranteed to return a non-null value.
if (invoke.hasUsedOutValue()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
index f596d2a..ea5f65d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
@@ -33,7 +33,6 @@
static final int UNKNOWN_RETURNED_ARGUMENT = -1;
static final boolean UNKNOWN_NEVER_RETURNS_NORMALLY = false;
static final AbstractValue UNKNOWN_ABSTRACT_RETURN_VALUE = UnknownValue.getInstance();
- static final boolean UNKNOWN_TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT = false;
static final boolean UNKNOWN_INITIALIZER_ENABLING_JAVA_ASSERTIONS = false;
static final boolean UNKNOWN_MAY_HAVE_SIDE_EFFECTS = true;
static final boolean UNKNOWN_RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS = false;
@@ -47,6 +46,11 @@
}
@Override
+ public boolean isDefault() {
+ return true;
+ }
+
+ @Override
public boolean cannotBeKept() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
index 31775ae..6a2bc86 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
@@ -28,6 +28,10 @@
Default
}
+ public boolean isDefault() {
+ return false;
+ }
+
public abstract boolean cannotBeKept();
public abstract boolean classInitializerMayBePostponed();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodResolutionOptimizationInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodResolutionOptimizationInfoCollection.java
new file mode 100644
index 0000000..6c2c13b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodResolutionOptimizationInfoCollection.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2023, 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.info;
+
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexReference;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Collection of optimization info for virtual methods with dynamic dispatch.
+ *
+ * <p>When a call to a virtual method does not have a single target, we cannot use the optimization
+ * info we compute for each method. Given the resolved method, this collection returns a piece of
+ * optimization info that is true for all possible dispatch targets (i.e., the join of the
+ * optimization of all possible dispatch targets).
+ */
+public class MethodResolutionOptimizationInfoCollection {
+
+ private static final MethodResolutionOptimizationInfoCollection EMPTY =
+ new MethodResolutionOptimizationInfoCollection(Collections.emptyMap());
+
+ private final Map<DexReference, MethodOptimizationInfo> backing;
+
+ MethodResolutionOptimizationInfoCollection(Map<DexReference, MethodOptimizationInfo> backing) {
+ this.backing = backing;
+ }
+
+ public static MethodResolutionOptimizationInfoCollection empty() {
+ return EMPTY;
+ }
+
+ public MethodOptimizationInfo get(DexEncodedMethod method, DexClass holder) {
+ MethodOptimizationInfo defaultValue = DefaultMethodOptimizationInfo.getInstance();
+ if (!holder.isProgramClass()) {
+ return defaultValue;
+ }
+ return backing.getOrDefault(method.getReference(), defaultValue);
+ }
+}