Refactor class inlining eligibility check to new ClassInlinerMethodConstraint
Bug: 173337498
Change-Id: If23d96e0a050a934893de0d5edfe2f49e0d78569
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
index b1b14fb..0cdf967 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
@@ -60,6 +61,9 @@
void setBridgeInfo(DexEncodedMethod method, BridgeInfo bridgeInfo);
+ void setClassInlinerMethodConstraint(
+ ProgramMethod method, ClassInlinerMethodConstraint classInlinerConstraint);
+
void setClassInlinerEligibility(DexEncodedMethod method, ClassInlinerEligibilityInfo eligibility);
void setInstanceInitializerInfoCollection(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerEligibilityInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerEligibilityInfo.java
index 35eaaf5..78e756d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerEligibilityInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerEligibilityInfo.java
@@ -21,8 +21,8 @@
*/
final OptionalBool returnsReceiver;
- final boolean hasMonitorOnReceiver;
- final boolean modifiesInstanceFields;
+ public final boolean hasMonitorOnReceiver;
+ public final boolean modifiesInstanceFields;
public ClassInlinerEligibilityInfo(
List<Pair<Invoke.Type, DexMethod>> callsReceiver,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index 371b79a..32e25f1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -53,6 +53,7 @@
import com.android.tools.r8.ir.optimize.Inliner.Reason;
import com.android.tools.r8.ir.optimize.InliningOracle;
import com.android.tools.r8.ir.optimize.classinliner.ClassInliner.EligibilityStatus;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.FieldOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
@@ -1096,33 +1097,22 @@
}
MethodOptimizationInfo optimizationInfo = singleTarget.getDefinition().getOptimizationInfo();
- ClassInlinerEligibilityInfo eligibility = optimizationInfo.getClassInlinerEligibility();
- if (eligibility == null) {
- return false;
- }
-
- if (root.isStaticGet()) {
- // If we are class inlining a singleton instance from a static-get, then we don't know the
- // value of the fields.
- ParameterUsage receiverUsage = optimizationInfo.getParameterUsages(0);
- if (receiverUsage == null || receiverUsage.hasFieldRead) {
+ ClassInlinerMethodConstraint classInlinerMethodConstraint =
+ optimizationInfo.getClassInlinerMethodConstraint();
+ if (root.isNewInstance()) {
+ if (!classInlinerMethodConstraint.isEligibleForNewInstanceClassInlining(singleTarget)) {
return false;
}
- if (eligibility.hasMonitorOnReceiver) {
- // We will not be able to remove the monitor instruction afterwards.
- return false;
- }
- if (eligibility.modifiesInstanceFields) {
- // The static instance could be accessed from elsewhere. Therefore, we cannot
- // allow side-effects to be removed and therefore cannot class inline method
- // calls that modifies the instance.
+ } else {
+ assert root.isStaticGet();
+ if (!classInlinerMethodConstraint.isEligibleForStaticGetClassInlining(singleTarget)) {
return false;
}
}
// If the method returns receiver and the return value is actually
// used in the code we need to make some additional checks.
- if (!eligibilityAcceptanceCheck.test(eligibility)) {
+ if (!eligibilityAcceptanceCheck.test(optimizationInfo.getClassInlinerEligibility())) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/AlwaysFalseClassInlinerMethodConstraint.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/AlwaysFalseClassInlinerMethodConstraint.java
new file mode 100644
index 0000000..c441134
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/AlwaysFalseClassInlinerMethodConstraint.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2021, 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.classinliner.constraint;
+
+import com.android.tools.r8.graph.ProgramMethod;
+
+public class AlwaysFalseClassInlinerMethodConstraint implements ClassInlinerMethodConstraint {
+
+ private static final AlwaysFalseClassInlinerMethodConstraint INSTANCE =
+ new AlwaysFalseClassInlinerMethodConstraint();
+
+ private AlwaysFalseClassInlinerMethodConstraint() {}
+
+ public static AlwaysFalseClassInlinerMethodConstraint getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isEligibleForNewInstanceClassInlining(ProgramMethod method) {
+ return false;
+ }
+
+ @Override
+ public boolean isEligibleForStaticGetClassInlining(ProgramMethod method) {
+ return false;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/AlwaysTrueClassInlinerMethodConstraint.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/AlwaysTrueClassInlinerMethodConstraint.java
new file mode 100644
index 0000000..3488111
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/AlwaysTrueClassInlinerMethodConstraint.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2021, 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.classinliner.constraint;
+
+import com.android.tools.r8.graph.ProgramMethod;
+
+public class AlwaysTrueClassInlinerMethodConstraint implements ClassInlinerMethodConstraint {
+
+ private static final AlwaysTrueClassInlinerMethodConstraint INSTANCE =
+ new AlwaysTrueClassInlinerMethodConstraint();
+
+ private AlwaysTrueClassInlinerMethodConstraint() {}
+
+ public static AlwaysTrueClassInlinerMethodConstraint getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isEligibleForNewInstanceClassInlining(ProgramMethod method) {
+ return true;
+ }
+
+ @Override
+ public boolean isEligibleForStaticGetClassInlining(ProgramMethod method) {
+ return true;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/ClassInlinerMethodConstraint.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/ClassInlinerMethodConstraint.java
new file mode 100644
index 0000000..e8ab3ab
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/ClassInlinerMethodConstraint.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2021, 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.classinliner.constraint;
+
+import com.android.tools.r8.graph.ProgramMethod;
+
+public interface ClassInlinerMethodConstraint {
+
+ boolean isEligibleForNewInstanceClassInlining(ProgramMethod method);
+
+ boolean isEligibleForStaticGetClassInlining(ProgramMethod method);
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/ClassInlinerMethodConstraintAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/ClassInlinerMethodConstraintAnalysis.java
new file mode 100644
index 0000000..fea67a4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/ClassInlinerMethodConstraintAnalysis.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2021, 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.classinliner.constraint;
+
+import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo;
+import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
+
+public class ClassInlinerMethodConstraintAnalysis {
+
+ public static ClassInlinerMethodConstraint analyze(
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo,
+ ParameterUsagesInfo parameterUsagesInfo) {
+ boolean isEligibleForNewInstanceClassInlining =
+ isEligibleForNewInstanceClassInlining(classInlinerEligibilityInfo);
+ boolean isEligibleForStaticGetClassInlining =
+ isEligibleForStaticGetClassInlining(classInlinerEligibilityInfo, parameterUsagesInfo);
+ if (isEligibleForNewInstanceClassInlining) {
+ if (isEligibleForStaticGetClassInlining) {
+ return alwaysTrue();
+ }
+ return onlyNewInstanceClassInlining();
+ }
+ assert !isEligibleForStaticGetClassInlining;
+ return alwaysFalse();
+ }
+
+ private static boolean isEligibleForNewInstanceClassInlining(
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo) {
+ return classInlinerEligibilityInfo != null;
+ }
+
+ private static boolean isEligibleForStaticGetClassInlining(
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo,
+ ParameterUsagesInfo parameterUsagesInfo) {
+ if (classInlinerEligibilityInfo == null || parameterUsagesInfo == null) {
+ return false;
+ }
+ if (classInlinerEligibilityInfo.hasMonitorOnReceiver) {
+ // We will not be able to remove the monitor instruction afterwards.
+ return false;
+ }
+ if (classInlinerEligibilityInfo.modifiesInstanceFields) {
+ // The static instance could be accessed from elsewhere. Therefore, we cannot allow
+ // side-effects to be removed and therefore cannot class inline method calls that modifies the
+ // instance.
+ return false;
+ }
+ ParameterUsage receiverUsage = parameterUsagesInfo.getParameterUsage(0);
+ if (receiverUsage == null) {
+ return false;
+ }
+ if (receiverUsage.hasFieldRead) {
+ // We don't know the value of the field.
+ return false;
+ }
+ return true;
+ }
+
+ private static AlwaysFalseClassInlinerMethodConstraint alwaysFalse() {
+ return AlwaysFalseClassInlinerMethodConstraint.getInstance();
+ }
+
+ private static AlwaysTrueClassInlinerMethodConstraint alwaysTrue() {
+ return AlwaysTrueClassInlinerMethodConstraint.getInstance();
+ }
+
+ private static OnlyNewInstanceClassInlinerMethodConstraint onlyNewInstanceClassInlining() {
+ return OnlyNewInstanceClassInlinerMethodConstraint.getInstance();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/OnlyNewInstanceClassInlinerMethodConstraint.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/OnlyNewInstanceClassInlinerMethodConstraint.java
new file mode 100644
index 0000000..d3f35d4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/constraint/OnlyNewInstanceClassInlinerMethodConstraint.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2021, 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.classinliner.constraint;
+
+import com.android.tools.r8.graph.ProgramMethod;
+
+public class OnlyNewInstanceClassInlinerMethodConstraint implements ClassInlinerMethodConstraint {
+
+ private static final OnlyNewInstanceClassInlinerMethodConstraint INSTANCE =
+ new OnlyNewInstanceClassInlinerMethodConstraint();
+
+ private OnlyNewInstanceClassInlinerMethodConstraint() {}
+
+ public static OnlyNewInstanceClassInlinerMethodConstraint getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isEligibleForNewInstanceClassInlining(ProgramMethod method) {
+ return true;
+ }
+
+ @Override
+ public boolean isEligibleForStaticGetClassInlining(ProgramMethod method) {
+ return false;
+ }
+}
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 a9854ee..45764df 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
@@ -13,6 +13,8 @@
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.AlwaysFalseClassInlinerMethodConstraint;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.DefaultInstanceInitializerInfo;
@@ -74,6 +76,11 @@
}
@Override
+ public ClassInlinerMethodConstraint getClassInlinerMethodConstraint() {
+ return AlwaysFalseClassInlinerMethodConstraint.getInstance();
+ }
+
+ @Override
public TypeElement getDynamicUpperBoundType() {
return UNKNOWN_TYPE;
}
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 93a330e..7cced9d 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
@@ -11,6 +11,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
@@ -35,6 +36,8 @@
public abstract boolean classInitializerMayBePostponed();
+ public abstract ClassInlinerMethodConstraint getClassInlinerMethodConstraint();
+
public abstract TypeElement getDynamicUpperBoundType();
public final TypeElement getDynamicUpperBoundTypeOrElse(TypeElement orElse) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index 7432e43..804b6b3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -90,6 +90,8 @@
import com.android.tools.r8.ir.optimize.DynamicTypeOptimization;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerReceiverAnalysis;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraintAnalysis;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsageBuilder;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeAnalyzer;
@@ -143,12 +145,16 @@
Timing timing) {
DexEncodedMethod definition = method.getDefinition();
identifyBridgeInfo(definition, code, feedback, timing);
- identifyClassInlinerEligibility(code, feedback, timing);
- identifyParameterUsages(definition, code, feedback, timing);
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo =
+ identifyClassInlinerEligibility(code, feedback, timing);
+ ParameterUsagesInfo parameterUsagesInfo =
+ identifyParameterUsages(definition, code, feedback, timing);
analyzeReturns(code, feedback, timing);
if (options.enableInlining) {
identifyInvokeSemanticsForInlining(definition, code, feedback, timing);
}
+ computeClassInlinerMethodConstraint(
+ method, code, feedback, classInlinerEligibilityInfo, parameterUsagesInfo, timing);
computeSimpleInliningConstraint(method, code, feedback, timing);
computeDynamicReturnType(dynamicTypeOptimization, feedback, definition, code, timing);
computeInitializedClassesOnNormalExit(feedback, definition, code, timing);
@@ -167,14 +173,17 @@
timing.end();
}
- private void identifyClassInlinerEligibility(
+ private ClassInlinerEligibilityInfo identifyClassInlinerEligibility(
IRCode code, OptimizationFeedback feedback, Timing timing) {
timing.begin("Identify class inliner eligibility");
- identifyClassInlinerEligibility(code, feedback);
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo =
+ identifyClassInlinerEligibility(code, feedback);
timing.end();
+ return classInlinerEligibilityInfo;
}
- private void identifyClassInlinerEligibility(IRCode code, OptimizationFeedback feedback) {
+ private ClassInlinerEligibilityInfo identifyClassInlinerEligibility(
+ IRCode code, OptimizationFeedback feedback) {
// Method eligibility is calculated in similar way for regular method
// and for the constructor. To be eligible method should only be using its
// receiver in the following ways:
@@ -193,14 +202,14 @@
boolean instanceInitializer = definition.isInstanceInitializer();
if (definition.isNative()
|| (!definition.isNonAbstractVirtualMethod() && !instanceInitializer)) {
- return;
+ return null;
}
feedback.setClassInlinerEligibility(definition, null); // To allow returns below.
Value receiver = code.getThis();
if (receiver.numberOfPhiUsers() > 0) {
- return;
+ return null;
}
List<Pair<Invoke.Type, DexMethod>> callsReceiver = new ArrayList<>();
@@ -229,17 +238,17 @@
InstancePut instancePutInstruction = insn.asInstancePut();
// Only allow field writes to the receiver.
if (!isReceiverAlias.test(instancePutInstruction.object())) {
- return;
+ return null;
}
// Do not allow the receiver to escape via a field write.
if (isReceiverAlias.test(instancePutInstruction.value())) {
- return;
+ return null;
}
modifiesInstanceFields = true;
}
DexField field = insn.asFieldInstruction().getField();
if (appView.appInfo().resolveField(field).isFailedOrUnknownResolution()) {
- return;
+ return null;
}
break;
}
@@ -257,7 +266,7 @@
break;
}
// We don't support other direct calls yet.
- return;
+ return null;
}
case INVOKE_STATIC:
@@ -265,27 +274,27 @@
InvokeStatic invoke = insn.asInvokeStatic();
DexClassAndMethod singleTarget = invoke.lookupSingleTarget(appView, context);
if (singleTarget == null) {
- return; // Not allowed.
+ return null; // Not allowed.
}
if (singleTarget.getReference() == dexItemFactory.objectsMethods.requireNonNull) {
if (!invoke.hasOutValue() || !invoke.outValue().hasAnyUsers()) {
continue;
}
}
- return;
+ return null;
}
case INVOKE_VIRTUAL:
{
InvokeVirtual invoke = insn.asInvokeVirtual();
if (ListUtils.lastIndexMatching(invoke.arguments(), isReceiverAlias) != 0) {
- return; // Not allowed.
+ return null; // Not allowed.
}
DexMethod invokedMethod = invoke.getInvokedMethod();
DexType returnType = invokedMethod.proto.returnType;
if (returnType.isClassType()
&& appView.appInfo().inSameHierarchy(returnType, context.getHolderType())) {
- return; // Not allowed, could introduce an alias of the receiver.
+ return null; // Not allowed, could introduce an alias of the receiver.
}
callsReceiver.add(new Pair<>(Invoke.Type.VIRTUAL, invokedMethod));
}
@@ -293,34 +302,35 @@
default:
// Other receiver usages make the method not eligible.
- return;
+ return null;
}
}
if (instanceInitializer && !seenSuperInitCall) {
// Call to super constructor not found?
- return;
+ return null;
}
boolean synchronizedVirtualMethod = definition.isSynchronized() && definition.isVirtualMethod();
-
- feedback.setClassInlinerEligibility(
- definition,
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo =
new ClassInlinerEligibilityInfo(
callsReceiver,
new ClassInlinerReceiverAnalysis(appView, definition, code).computeReturnsReceiver(),
seenMonitor || synchronizedVirtualMethod,
- modifiesInstanceFields));
+ modifiesInstanceFields);
+ feedback.setClassInlinerEligibility(definition, classInlinerEligibilityInfo);
+ return classInlinerEligibilityInfo;
}
- private void identifyParameterUsages(
+ private ParameterUsagesInfo identifyParameterUsages(
DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
timing.begin("Identify parameter usages");
- identifyParameterUsages(method, code, feedback);
+ ParameterUsagesInfo parameterUsagesInfo = identifyParameterUsages(method, code, feedback);
timing.end();
+ return parameterUsagesInfo;
}
- private void identifyParameterUsages(
+ private ParameterUsagesInfo identifyParameterUsages(
DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
List<ParameterUsage> usages = new ArrayList<>();
List<Value> values = code.collectArguments();
@@ -331,11 +341,10 @@
usages.add(usage);
}
}
- feedback.setParameterUsages(
- method,
- usages.isEmpty()
- ? DefaultMethodOptimizationInfo.UNKNOWN_PARAMETER_USAGE_INFO
- : new ParameterUsagesInfo(usages));
+ ParameterUsagesInfo parameterUsagesInfo =
+ !usages.isEmpty() ? new ParameterUsagesInfo(usages) : null;
+ feedback.setParameterUsages(method, parameterUsagesInfo);
+ return parameterUsagesInfo;
}
private ParameterUsage collectParameterUsages(int i, Value root) {
@@ -969,6 +978,31 @@
return true;
}
+ private void computeClassInlinerMethodConstraint(
+ ProgramMethod method,
+ IRCode code,
+ OptimizationFeedback feedback,
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo,
+ ParameterUsagesInfo parameterUsagesInfo,
+ Timing timing) {
+ timing.begin("Compute class inlining constraint");
+ computeClassInlinerMethodConstraint(
+ method, code, feedback, classInlinerEligibilityInfo, parameterUsagesInfo);
+ timing.end();
+ }
+
+ private void computeClassInlinerMethodConstraint(
+ ProgramMethod method,
+ IRCode code,
+ OptimizationFeedback feedback,
+ ClassInlinerEligibilityInfo classInlinerEligibilityInfo,
+ ParameterUsagesInfo parameterUsagesInfo) {
+ ClassInlinerMethodConstraint classInlinerMethodConstraint =
+ ClassInlinerMethodConstraintAnalysis.analyze(
+ classInlinerEligibilityInfo, parameterUsagesInfo);
+ feedback.setClassInlinerMethodConstraint(method, classInlinerMethodConstraint);
+ }
+
private void computeSimpleInliningConstraint(
ProgramMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
if (appView.options().enableSimpleInliningConstraints) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
index 1236ed6..39f725d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -250,11 +251,18 @@
}
@Override
- public void setBridgeInfo(DexEncodedMethod method, BridgeInfo bridgeInfo) {
+ public synchronized void setBridgeInfo(DexEncodedMethod method, BridgeInfo bridgeInfo) {
getMethodOptimizationInfoForUpdating(method).setBridgeInfo(bridgeInfo);
}
@Override
+ public synchronized void setClassInlinerMethodConstraint(
+ ProgramMethod method, ClassInlinerMethodConstraint classInlinerConstraint) {
+ getMethodOptimizationInfoForUpdating(method)
+ .setClassInlinerMethodConstraint(classInlinerConstraint);
+ }
+
+ @Override
public synchronized void setClassInlinerEligibility(
DexEncodedMethod method, ClassInlinerEligibilityInfo eligibility) {
getMethodOptimizationInfoForUpdating(method).setClassInlinerEligibility(eligibility);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
index 299f7ce..3b46f4e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -113,6 +114,10 @@
public void setBridgeInfo(DexEncodedMethod method, BridgeInfo bridgeInfo) {}
@Override
+ public void setClassInlinerMethodConstraint(
+ ProgramMethod method, ClassInlinerMethodConstraint classInlinerConstraint) {}
+
+ @Override
public void setClassInlinerEligibility(
DexEncodedMethod method, ClassInlinerEligibilityInfo eligibility) {}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
index 945d84a..2624486 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -163,6 +164,12 @@
}
@Override
+ public void setClassInlinerMethodConstraint(
+ ProgramMethod method, ClassInlinerMethodConstraint classInlinerConstraint) {
+ // Ignored.
+ }
+
+ @Override
public void setClassInlinerEligibility(
DexEncodedMethod method, ClassInlinerEligibilityInfo eligibility) {
// Ignored.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/ParameterUsagesInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/ParameterUsagesInfo.java
index 921ae28..4389193 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/ParameterUsagesInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/ParameterUsagesInfo.java
@@ -39,7 +39,7 @@
parametersUsages.stream().map(usage -> usage.index).collect(Collectors.toSet()).size();
}
- ParameterUsage getParameterUsage(int index) {
+ public ParameterUsage getParameterUsage(int index) {
for (ParameterUsage usage : parametersUsages) {
if (usage.index == index) {
return usage;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
index a179561..43667c8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
@@ -16,6 +16,8 @@
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.AlwaysFalseClassInlinerMethodConstraint;
+import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
@@ -33,6 +35,8 @@
private int returnedArgument = DefaultMethodOptimizationInfo.UNKNOWN_RETURNED_ARGUMENT;
private AbstractValue abstractReturnValue =
DefaultMethodOptimizationInfo.UNKNOWN_ABSTRACT_RETURN_VALUE;
+ private ClassInlinerMethodConstraint classInlinerConstraint =
+ AlwaysFalseClassInlinerMethodConstraint.getInstance();
private TypeElement returnsObjectWithUpperBoundType = DefaultMethodOptimizationInfo.UNKNOWN_TYPE;
private ClassTypeElement returnsObjectWithLowerBoundType =
DefaultMethodOptimizationInfo.UNKNOWN_CLASS_TYPE;
@@ -239,6 +243,15 @@
}
@Override
+ public ClassInlinerMethodConstraint getClassInlinerMethodConstraint() {
+ return classInlinerConstraint;
+ }
+
+ void setClassInlinerMethodConstraint(ClassInlinerMethodConstraint classInlinerConstraint) {
+ this.classInlinerConstraint = classInlinerConstraint;
+ }
+
+ @Override
public TypeElement getDynamicUpperBoundType() {
return returnsObjectWithUpperBoundType;
}