Remove class inliner bail-out from singleton field read
Change-Id: Ic7cdff89cf6dc028fe93568af0123ac88736295b
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java
index f0af9b4..4db63a6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/ObjectState.java
@@ -8,10 +8,12 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
+import java.util.function.Predicate;
public abstract class ObjectState {
@@ -25,6 +27,22 @@
public abstract void forEachAbstractFieldValue(BiConsumer<DexField, AbstractValue> consumer);
+ public final boolean hasMaterializableFieldValueThatMatches(
+ AppView<AppInfoWithLiveness> appView,
+ DexEncodedField field,
+ ProgramMethod context,
+ Predicate<SingleValue> predicate) {
+ AbstractValue abstractValue = getAbstractFieldValue(field);
+ if (!abstractValue.isSingleValue()) {
+ return false;
+ }
+ SingleValue singleValue = abstractValue.asSingleValue();
+ if (!singleValue.isMaterializableInContext(appView, context)) {
+ return false;
+ }
+ return predicate.test(singleValue);
+ }
+
public abstract AbstractValue getAbstractFieldValue(DexEncodedField field);
public abstract boolean isEmpty();
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 91a2d83..7b97eb6 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
@@ -256,10 +256,6 @@
}
if (user.isInstanceGet()) {
- if (root.isStaticGet()) {
- // We don't have a replacement for this field read.
- return user; // Not eligible.
- }
DexEncodedField field =
appView
.appInfo()
@@ -268,6 +264,11 @@
if (field == null || field.isStatic()) {
return user; // Not eligible.
}
+ if (root.isStaticGet()
+ && !objectState.hasMaterializableFieldValueThatMatches(
+ appView, field, method, AbstractValue::isSingleConstValue)) {
+ return user; // Not eligible.
+ }
continue;
}
@@ -324,23 +325,20 @@
}
// Eligible constructor call (for new instance roots only).
- if (user.isInvokeDirect()) {
+ if (user.isInvokeConstructor(dexItemFactory)) {
InvokeDirect invoke = user.asInvokeDirect();
- if (dexItemFactory.isConstructor(invoke.getInvokedMethod())) {
- boolean isCorrespondingConstructorCall =
- root.isNewInstance()
- && !invoke.inValues().isEmpty()
- && root.outValue() == invoke.getReceiver();
- if (isCorrespondingConstructorCall) {
- InliningInfo inliningInfo = isEligibleConstructorCall(invoke, singleProgramTarget);
- if (inliningInfo != null) {
- methodCallsOnInstance.put(invoke, inliningInfo);
- continue;
- }
+ boolean isCorrespondingConstructorCall =
+ root.isNewInstance()
+ && !invoke.inValues().isEmpty()
+ && root.outValue() == invoke.getReceiver();
+ if (isCorrespondingConstructorCall) {
+ InliningInfo inliningInfo = isEligibleConstructorCall(invoke, singleProgramTarget);
+ if (inliningInfo != null) {
+ methodCallsOnInstance.put(invoke, inliningInfo);
+ continue;
}
- assert !isExtraMethodCall(invoke);
- return user; // Not eligible.
}
+ return user; // Not eligible.
}
// Eligible virtual method call on the instance as a receiver.
@@ -483,7 +481,7 @@
}
DexProgramClass holder =
- asProgramClassOrNull(appView.definitionForHolder(invokedMethod));
+ asProgramClassOrNull(appView.definitionForHolder(invokedMethod, method));
if (holder == null) {
throw new IllegalClassInlinerStateException();
}
@@ -932,7 +930,8 @@
if (parent == null) {
return null;
}
- DexProgramClass parentClass = asProgramClassOrNull(appView.definitionForHolder(parent));
+ DexProgramClass parentClass =
+ asProgramClassOrNull(appView.definitionForHolder(parent, method));
if (parentClass == null) {
return null;
}