Revert "Move Array length to ObjectState"
This reverts commit 277219e668ecca2092570a3795bcd76ff4d90e4b.
Reason for revert: Breaks FieldInitializedByConstantArgumentSubtypeTest
Change-Id: Iba1c7635c100fa10acad0b9c36fe19ed5d31c8f9
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index 0303ba7..30060d9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueNull;
@@ -24,7 +25,6 @@
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.analysis.value.objectstate.EnumValuesObjectState;
import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
-import com.android.tools.r8.ir.analysis.value.objectstate.ObjectStateAnalysis;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.IRCode;
@@ -35,6 +35,8 @@
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
+import com.android.tools.r8.ir.optimize.info.field.InstanceFieldArgumentInitializationInfo;
+import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Timing;
import java.util.IdentityHashMap;
@@ -238,7 +240,7 @@
// This implicitely answers null if the value could not get computed.
if (valuesValue.isSingleFieldValue()) {
SingleFieldValue fieldValue = valuesValue.asSingleFieldValue();
- if (fieldValue.getObjectState().isEnumValuesObjectState()) {
+ if (fieldValue.getState().isEnumValuesObjectState()) {
return fieldValue;
}
}
@@ -437,12 +439,62 @@
}
private ObjectState computeObjectState(Value value) {
- // TODO(b/204159267): Move this logic into Instruction#getAbstractValue in NewInstance.
- return ObjectStateAnalysis.computeObjectState(value, appView, context);
+ assert !value.hasAliasedValue();
+ if (!value.isDefinedByInstructionSatisfying(Instruction::isNewInstance)) {
+ return ObjectState.empty();
+ }
+
+ NewInstance newInstance = value.definition.asNewInstance();
+ InvokeDirect uniqueConstructorInvoke =
+ newInstance.getUniqueConstructorInvoke(appView.dexItemFactory());
+ if (uniqueConstructorInvoke == null) {
+ return ObjectState.empty();
+ }
+
+ DexClassAndMethod singleTarget = uniqueConstructorInvoke.lookupSingleTarget(appView, context);
+ if (singleTarget == null) {
+ return ObjectState.empty();
+ }
+
+ InstanceFieldInitializationInfoCollection initializationInfos =
+ singleTarget
+ .getDefinition()
+ .getOptimizationInfo()
+ .getInstanceInitializerInfo(uniqueConstructorInvoke)
+ .fieldInitializationInfos();
+ if (initializationInfos.isEmpty()) {
+ return ObjectState.empty();
+ }
+
+ ObjectState.Builder builder = ObjectState.builder();
+ initializationInfos.forEach(
+ appView,
+ (field, initializationInfo) -> {
+ // If the instance field is not written only in the instance initializer, then we can't
+ // conclude that this field will have a constant value.
+ //
+ // We have special handling for library fields that satisfy the property that they are
+ // only written in their corresponding instance initializers. This is needed since we
+ // don't analyze these instance initializers in the Enqueuer, as they are in the library.
+ if (!appView.appInfo().isInstanceFieldWrittenOnlyInInstanceInitializers(field)
+ && !appView.dexItemFactory().enumMembers.isNameOrOrdinalField(field.getReference())) {
+ return;
+ }
+ if (initializationInfo.isArgumentInitializationInfo()) {
+ InstanceFieldArgumentInitializationInfo argumentInitializationInfo =
+ initializationInfo.asArgumentInitializationInfo();
+ Value argument =
+ uniqueConstructorInvoke.getArgument(argumentInitializationInfo.getArgumentIndex());
+ builder.recordFieldHasValue(field, argument.getAbstractValue(appView, context));
+ } else if (initializationInfo.isSingleValue()) {
+ builder.recordFieldHasValue(field, initializationInfo.asSingleValue());
+ }
+ });
+ return builder.build();
}
private boolean isEnumValuesArray(Value value) {
SingleFieldValue singleFieldValue = computeSingleEnumFieldValueForValuesArray(value);
- return singleFieldValue != null && singleFieldValue.getObjectState().isEnumValuesObjectState();
+ return singleFieldValue != null && singleFieldValue.getState().isEnumValuesObjectState();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java
index e57052f..0b9a6cd 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValues.java
@@ -59,18 +59,17 @@
DexEncodedField staticField, AbstractValue value, DexItemFactory factory) {
if (factory.enumMembers.isValuesFieldCandidate(staticField, staticField.getHolderType())) {
if (value.isSingleFieldValue()
- && value.asSingleFieldValue().getObjectState().isEnumValuesObjectState()) {
+ && value.asSingleFieldValue().getState().isEnumValuesObjectState()) {
assert valuesCandidateAbstractValue == null
|| valuesCandidateAbstractValue.equals(value);
valuesCandidateAbstractValue = value;
enumObjectStateBuilder.put(
- staticField.getReference(), value.asSingleFieldValue().getObjectState());
+ staticField.getReference(), value.asSingleFieldValue().getState());
}
} else if (factory.enumMembers.isEnumField(staticField, staticField.getHolderType())) {
- if (value.isSingleFieldValue()
- && !value.asSingleFieldValue().getObjectState().isEmpty()) {
+ if (value.isSingleFieldValue() && !value.asSingleFieldValue().getState().isEmpty()) {
enumObjectStateBuilder.put(
- staticField.getReference(), value.asSingleFieldValue().getObjectState());
+ staticField.getReference(), value.asSingleFieldValue().getState());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
index 854ea6d..d69ca26 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
-import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
public abstract class AbstractValue {
@@ -58,32 +57,14 @@
return null;
}
- public boolean hasObjectState() {
+ public boolean isKnownLengthArrayValue() {
return false;
}
- public ObjectState getObjectState() {
- throw new UnsupportedOperationException(
- "Abstract value " + this + " does not have any object state.");
- }
-
- public boolean isStatefulObjectValue() {
- return false;
- }
-
- public StatefulObjectValue asStatefulObjectValue() {
+ public KnownLengthArrayValue asKnownLengthArrayValue() {
return null;
}
- public boolean hasKnownArrayLength() {
- return false;
- }
-
- public int getKnownArrayLength() {
- throw new UnsupportedOperationException(
- "Abstract value " + this + " does not have a known array length.");
- }
-
public boolean isSingleConstValue() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValueFactory.java b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValueFactory.java
index bc1a554..e1cdb6c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValueFactory.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValueFactory.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.value.objectstate.KnownLengthArrayState;
import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import java.util.concurrent.ConcurrentHashMap;
@@ -20,15 +19,15 @@
private ConcurrentHashMap<Long, SingleNumberValue> singleNumberValues = new ConcurrentHashMap<>();
private ConcurrentHashMap<DexString, SingleStringValue> singleStringValues =
new ConcurrentHashMap<>();
- private ConcurrentHashMap<Integer, KnownLengthArrayState> knownArrayLengthStates =
+ private ConcurrentHashMap<Integer, KnownLengthArrayValue> knownArrayLengthValues =
new ConcurrentHashMap<>();
public SingleConstClassValue createSingleConstClassValue(DexType type) {
return singleConstClassValues.computeIfAbsent(type, SingleConstClassValue::new);
}
- public KnownLengthArrayState createKnownLengthArrayState(int length) {
- return knownArrayLengthStates.computeIfAbsent(length, KnownLengthArrayState::new);
+ public AbstractValue createKnownLengthArrayValue(int length) {
+ return knownArrayLengthValues.computeIfAbsent(length, KnownLengthArrayValue::new);
}
public SingleFieldValue createSingleFieldValue(DexField field, ObjectState state) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/KnownLengthArrayValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/KnownLengthArrayValue.java
new file mode 100644
index 0000000..9721031
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/KnownLengthArrayValue.java
@@ -0,0 +1,57 @@
+// 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.analysis.value;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+/** A KnownLengthArrayValue implicitly implies the value is non null. */
+public class KnownLengthArrayValue extends AbstractValue {
+
+ private final int length;
+
+ public KnownLengthArrayValue(int length) {
+ this.length = length;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ @Override
+ public boolean isKnownLengthArrayValue() {
+ return true;
+ }
+
+ @Override
+ public KnownLengthArrayValue asKnownLengthArrayValue() {
+ return this;
+ }
+
+ @Override
+ public boolean isNonTrivial() {
+ return true;
+ }
+
+ @Override
+ public AbstractValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLens lens) {
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return this == o;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public String toString() {
+ return "KnownLengthArrayValue(len=" + length + ")";
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
index b499b81..71a6dbf 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
@@ -48,11 +48,7 @@
return field.lookupOnClass(holder);
}
- @Override
- public abstract ObjectState getObjectState();
-
- @Override
- public abstract boolean hasObjectState();
+ public abstract ObjectState getState();
public boolean mayHaveFinalizeMethodDirectlyOrIndirectly(AppView<AppInfoWithLiveness> appView) {
DexType fieldType = field.type;
@@ -144,6 +140,6 @@
}
}
return factory.createSingleFieldValue(
- lens.lookupField(field), getObjectState().rewrittenWithLens(appView, lens));
+ lens.lookupField(field), getState().rewrittenWithLens(appView, lens));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatefulFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatefulFieldValue.java
index 4191a9c..d14f5a9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatefulFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatefulFieldValue.java
@@ -20,22 +20,7 @@
}
@Override
- public boolean hasKnownArrayLength() {
- return getObjectState().hasKnownArrayLength();
- }
-
- @Override
- public int getKnownArrayLength() {
- return getObjectState().getKnownArrayLength();
- }
-
- @Override
- public boolean hasObjectState() {
- return true;
- }
-
- @Override
- public ObjectState getObjectState() {
+ public ObjectState getState() {
return state;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatelessFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatelessFieldValue.java
index 3845594..809b365 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatelessFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStatelessFieldValue.java
@@ -15,16 +15,11 @@
}
@Override
- public ObjectState getObjectState() {
+ public ObjectState getState() {
return ObjectState.empty();
}
@Override
- public boolean hasObjectState() {
- return false;
- }
-
- @Override
public String toString() {
return "SingleStatelessFieldValue(" + field.toSourceString() + ")";
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java
deleted file mode 100644
index 39174da..0000000
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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.analysis.value;
-
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.GraphLens;
-import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-
-/** A KnownLengthArrayValue implicitly implies the value is non null. */
-public class StatefulObjectValue extends AbstractValue {
-
- private final ObjectState state;
-
- StatefulObjectValue(ObjectState state) {
- assert !state.isEmpty();
- this.state = state;
- }
-
- public static AbstractValue create(ObjectState objectState) {
- return objectState.isEmpty()
- ? UnknownValue.getInstance()
- : new StatefulObjectValue(objectState);
- }
-
- @Override
- public boolean isNonTrivial() {
- return true;
- }
-
- @Override
- public boolean isStatefulObjectValue() {
- return true;
- }
-
- @Override
- public StatefulObjectValue asStatefulObjectValue() {
- return this;
- }
-
- @Override
- public boolean hasKnownArrayLength() {
- return getObjectState().hasKnownArrayLength();
- }
-
- @Override
- public int getKnownArrayLength() {
- return getObjectState().getKnownArrayLength();
- }
-
- @Override
- public AbstractValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLens lens) {
- return create(getObjectState().rewrittenWithLens(appView, lens));
- }
-
- @Override
- public boolean hasObjectState() {
- return true;
- }
-
- @Override
- public ObjectState getObjectState() {
- return state;
- }
-
- @Override
- public String toString() {
- return "StatefulValue";
- }
-
- @Override
- public boolean equals(Object o) {
- if (getClass() != o.getClass()) {
- return false;
- }
- StatefulObjectValue statefulObjectValue = (StatefulObjectValue) o;
- return state.equals(statefulObjectValue.state);
- }
-
- @Override
- public int hashCode() {
- return state.hashCode();
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EnumValuesObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EnumValuesObjectState.java
index 817b166..397e79f 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EnumValuesObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EnumValuesObjectState.java
@@ -45,16 +45,6 @@
}
@Override
- public boolean hasKnownArrayLength() {
- return true;
- }
-
- @Override
- public int getKnownArrayLength() {
- return state.length;
- }
-
- @Override
public boolean isEnumValuesObjectState() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java
deleted file mode 100644
index a379776..0000000
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.analysis.value.objectstate;
-
-import com.android.tools.r8.graph.AppView;
-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.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.analysis.value.UnknownValue;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.function.BiConsumer;
-
-public class KnownLengthArrayState extends ObjectState {
-
- private final int length;
-
- public KnownLengthArrayState(int length) {
- this.length = length;
- }
-
- @Override
- public void forEachAbstractFieldValue(BiConsumer<DexField, AbstractValue> consumer) {
- // Intentionally empty.
- }
-
- @Override
- public AbstractValue getAbstractFieldValue(DexEncodedField field) {
- return UnknownValue.getInstance();
- }
-
- @Override
- public boolean isEmpty() {
- return false;
- }
-
- @Override
- public boolean hasKnownArrayLength() {
- return true;
- }
-
- @Override
- public int getKnownArrayLength() {
- return length;
- }
-
- @Override
- public ObjectState rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLens lens) {
- return this;
- }
-
- @Override
- public boolean equals(Object o) {
- return this == o;
- }
-
- @Override
- public int hashCode() {
- return System.identityHashCode(this);
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectState.java
index b81fb32..f709c59 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectState.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.analysis.value.objectstate;
-import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
@@ -59,15 +58,6 @@
@Override
public abstract int hashCode();
- public boolean hasKnownArrayLength() {
- return false;
- }
-
- public int getKnownArrayLength() {
- // Override this method if hasKnownArrayLength answers true.
- throw new Unreachable();
- }
-
public boolean isEnumValuesObjectState() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectStateAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectStateAnalysis.java
deleted file mode 100644
index 414b74f..0000000
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/ObjectStateAnalysis.java
+++ /dev/null
@@ -1,94 +0,0 @@
-// 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.analysis.value.objectstate;
-
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InvokeDirect;
-import com.android.tools.r8.ir.code.NewInstance;
-import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.optimize.info.field.InstanceFieldArgumentInitializationInfo;
-import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-
-public class ObjectStateAnalysis {
-
- public static ObjectState computeObjectState(
- Value value, AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
- assert !value.hasAliasedValue();
- if (value.isDefinedByInstructionSatisfying(
- i -> i.isNewArrayEmpty() || i.isNewArrayFilledData())) {
- return computeNewArrayObjectState(value, appView, context);
- }
- if (value.isDefinedByInstructionSatisfying(Instruction::isNewInstance)) {
- return computeNewInstanceObjectState(value, appView, context);
- }
- return ObjectState.empty();
- }
-
- private static ObjectState computeNewArrayObjectState(
- Value value, AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
- AbstractValue abstractValue = value.definition.getAbstractValue(appView, context);
- if (abstractValue.isStatefulObjectValue()) {
- // TODO(b/204272377): Avoid wrapping and unwrapping the object state.
- return abstractValue.asStatefulObjectValue().getObjectState();
- }
- return ObjectState.empty();
- }
-
- private static ObjectState computeNewInstanceObjectState(
- Value value, AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
- NewInstance newInstance = value.definition.asNewInstance();
- InvokeDirect uniqueConstructorInvoke =
- newInstance.getUniqueConstructorInvoke(appView.dexItemFactory());
- if (uniqueConstructorInvoke == null) {
- return ObjectState.empty();
- }
-
- DexClassAndMethod singleTarget = uniqueConstructorInvoke.lookupSingleTarget(appView, context);
- if (singleTarget == null) {
- return ObjectState.empty();
- }
-
- InstanceFieldInitializationInfoCollection initializationInfos =
- singleTarget
- .getDefinition()
- .getOptimizationInfo()
- .getInstanceInitializerInfo(uniqueConstructorInvoke)
- .fieldInitializationInfos();
- if (initializationInfos.isEmpty()) {
- return ObjectState.empty();
- }
-
- ObjectState.Builder builder = ObjectState.builder();
- initializationInfos.forEach(
- appView,
- (field, initializationInfo) -> {
- // If the instance field is not written only in the instance initializer, then we can't
- // conclude that this field will have a constant value.
- //
- // We have special handling for library fields that satisfy the property that they are
- // only written in their corresponding instance initializers. This is needed since we
- // don't analyze these instance initializers in the Enqueuer, as they are in the library.
- if (!appView.appInfo().isInstanceFieldWrittenOnlyInInstanceInitializers(field)
- && !appView.dexItemFactory().enumMembers.isNameOrOrdinalField(field.getReference())) {
- return;
- }
- if (initializationInfo.isArgumentInitializationInfo()) {
- InstanceFieldArgumentInitializationInfo argumentInitializationInfo =
- initializationInfo.asArgumentInitializationInfo();
- Value argument =
- uniqueConstructorInvoke.getArgument(argumentInitializationInfo.getArgumentIndex());
- builder.recordFieldHasValue(field, argument.getAbstractValue(appView, context));
- } else if (initializationInfo.isSingleValue()) {
- builder.recordFieldHasValue(field, initializationInfo.asSingleValue());
- }
- });
- return builder.build();
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
index e1bb5bf..9aff428 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
@@ -276,10 +276,10 @@
return true;
}
AbstractValue abstractValue = array().getAliasedValue().getAbstractValue(appView, context);
- if (!abstractValue.hasKnownArrayLength()) {
+ if (!abstractValue.isKnownLengthArrayValue()) {
return true;
}
- int newArraySize = abstractValue.getKnownArrayLength();
+ int newArraySize = abstractValue.asKnownLengthArrayValue().getLength();
int index = index().getConstInstruction().asConstNumber().getIntValue();
return newArraySize <= 0 || index < 0 || newArraySize <= index;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index 3be3d3d..3ddbcbd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.analysis.value.StatefulObjectValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -91,10 +90,9 @@
AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (!instructionMayHaveSideEffects(appView, context) && size().getType().isInt()) {
assert !instructionInstanceCanThrow();
- return StatefulObjectValue.create(
- appView
- .abstractValueFactory()
- .createKnownLengthArrayState(size().definition.asConstNumber().getIntValue()));
+ return appView
+ .abstractValueFactory()
+ .createKnownLengthArrayValue(size().definition.asConstNumber().getIntValue());
}
return UnknownValue.getInstance();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index fb04f03..ce235d4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.analysis.value.StatefulObjectValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -128,8 +127,7 @@
AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (!instructionMayHaveSideEffects(appView, context) && size <= Integer.MAX_VALUE) {
assert !instructionInstanceCanThrow();
- return StatefulObjectValue.create(
- appView.abstractValueFactory().createKnownLengthArrayState((int) size));
+ return appView.abstractValueFactory().createKnownLengthArrayValue((int) size);
}
return UnknownValue.getInstance();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index dae6f04..bcd27e6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -3451,7 +3451,7 @@
}
AbstractValue abstractValue = array.getAbstractValue(appView, code.context());
- if (!abstractValue.hasKnownArrayLength() && !array.isNeverNull()) {
+ if (!abstractValue.isKnownLengthArrayValue() && !array.isNeverNull()) {
continue;
}
Instruction arrayDefinition = array.getDefinition();
@@ -3468,13 +3468,15 @@
continue;
}
iterator.replaceCurrentInstructionWithConstInt(code, (int) size);
- } else if (abstractValue.hasKnownArrayLength()) {
- iterator.replaceCurrentInstructionWithConstInt(code, abstractValue.getKnownArrayLength());
+ } else if (abstractValue.isKnownLengthArrayValue()) {
+ iterator.replaceCurrentInstructionWithConstInt(
+ code, abstractValue.asKnownLengthArrayValue().getLength());
} else {
continue;
}
phiUsers.forEach(Phi::removeTrivialPhi);
+ // TODO(139489070): static-get of constant array
}
assert code.isConsistentSSA();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 206c455..9e8d052 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -401,8 +401,12 @@
if (abstractValue.isUnknown() && !definition.isStatic()) {
AbstractValue abstractReceiverValue =
current.asInstanceGet().object().getAbstractValue(appView, code.context());
- if (abstractReceiverValue.hasObjectState()) {
- abstractValue = abstractReceiverValue.getObjectState().getAbstractFieldValue(definition);
+ if (abstractReceiverValue.isSingleFieldValue()) {
+ abstractValue =
+ abstractReceiverValue
+ .asSingleFieldValue()
+ .getState()
+ .getAbstractFieldValue(definition);
}
}
} else if (definition.isStatic()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index 290f25b..e42266b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -421,7 +421,7 @@
SingleFieldValue singleFieldValue =
field.getDefinition().getOptimizationInfo().getAbstractValue().asSingleFieldValue();
if (singleFieldValue != null) {
- applyObjectState(staticGet.outValue(), singleFieldValue.getObjectState());
+ applyObjectState(staticGet.outValue(), singleFieldValue.getState());
}
}
}
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 82322c7..487d677 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
@@ -191,7 +191,7 @@
AbstractValue abstractValue = optimizationInfo.getAbstractValue();
objectState =
abstractValue.isSingleFieldValue()
- ? abstractValue.asSingleFieldValue().getObjectState()
+ ? abstractValue.asSingleFieldValue().getState()
: ObjectState.empty();
return EligibilityStatus.ELIGIBLE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index ff79200..f51dc69 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -356,7 +356,7 @@
if (encodedField == null) {
return null;
}
- return abstractValue.asSingleFieldValue().getObjectState().getAbstractFieldValue(encodedField);
+ return abstractValue.asSingleFieldValue().getState().getAbstractFieldValue(encodedField);
}
private static final class EnumSwitchInfo {
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 b5ced8c..15819c7 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
@@ -65,9 +65,6 @@
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.analysis.value.StatefulObjectValue;
-import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
-import com.android.tools.r8.ir.analysis.value.objectstate.ObjectStateAnalysis;
import com.android.tools.r8.ir.code.AliasedValueConfiguration;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.AssumeAndCheckCastAliasedValueConfiguration;
@@ -212,13 +209,6 @@
checkCastAndInstanceOfMethodSpecialization.addCandidateForOptimization(
context, abstractReturnValue, methodProcessor);
}
- } else if (returnValue.getType().isReferenceType()) {
- // TODO(b/204159267): Move this logic into Instruction#getAbstractValue in NewInstance.
- ObjectState objectState =
- ObjectStateAnalysis.computeObjectState(aliasedValue, appView, context);
- // TODO(b/204272377): Avoid wrapping and unwrapping the object state.
- feedback.methodReturnsAbstractValue(
- method, appView, StatefulObjectValue.create(objectState));
}
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/StatePropagationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/StatePropagationTest.java
deleted file mode 100644
index f4b90ed..0000000
--- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/StatePropagationTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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.membervaluepropagation;
-
-import static org.junit.Assert.assertEquals;
-
-import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ir.optimize.membervaluepropagation.StatePropagationTest.TestClass.Data;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class StatePropagationTest extends TestBase {
-
- private final TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimesAndApiLevels().build();
- }
-
- public StatePropagationTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- @Test
- public void test() throws Exception {
- testForR8(parameters.getBackend())
- .addInnerClasses(StatePropagationTest.class)
- .addKeepMainRule(TestClass.class)
- .setMinApi(parameters.getApiLevel())
- .enableInliningAnnotations()
- .enableNeverClassInliningAnnotations()
- .compile()
- .inspect(this::inspect)
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutputLines("1", "1.0", "2", "2.0");
- }
-
- private void inspect(CodeInspector inspector) {
- ClassSubject data = inspector.clazz(Data.class);
- assertEquals(0, data.allInstanceFields().size());
- }
-
- static class TestClass {
-
- @NeverClassInline
- static class Data {
- final int i;
- final float j;
-
- private Data(int i, float j) {
- this.i = i;
- this.j = j;
- }
- }
-
- @NeverInline
- public static Data getData1() {
- return new Data(1, 1.0f);
- }
-
- @NeverInline
- public static Data getData2() {
- return new Data(2, 2.0f);
- }
-
- public static void main(String[] args) {
- Data data1 = getData1();
- Data data2 = getData2();
- System.out.println(data1.i);
- System.out.println(data1.j);
- System.out.println(data2.i);
- System.out.println(data2.j);
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java b/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java
index c38c66f..5a7be26 100644
--- a/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java
@@ -68,7 +68,7 @@
.addProgramClasses(Main.class)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(expectedOutput)
- .inspect(i -> inspect(i, true));
+ .inspect(this::inspect);
}
@Test public void r8() throws Exception {
@@ -80,10 +80,10 @@
.enableInliningAnnotations()
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(expectedOutput)
- .inspect(i -> inspect(i, false));
+ .inspect(this::inspect);
}
- private void inspect(CodeInspector inspector, boolean d8) {
+ private void inspect(CodeInspector inspector) {
ClassSubject mainClass = inspector.clazz(Main.class);
assertTrue(mainClass.isPresent());
@@ -104,10 +104,10 @@
// TODO(139489070): these should be rewritten and result in 0 array-length bytecodes
MethodSubject staticConstants = mainClass.uniqueMethodWithName("staticConstants");
- assertArrayLengthCallCount(staticConstants, (d8 || debugMode) ? 3 : 0);
+ assertArrayLengthCallCount(staticConstants, 3);
MethodSubject staticNonConstants = mainClass.uniqueMethodWithName("staticNonConstants");
- assertArrayLengthCallCount(staticNonConstants, (d8 || debugMode) ? 2 : 0);
+ assertArrayLengthCallCount(staticNonConstants, 2);
}
private static void assertArrayLengthCallCount(MethodSubject subject, int expected) {
@@ -200,7 +200,7 @@
}
private static String[] mutable = { "one" };
- private static final String[] runtimeInit = {"two"};
+ private static final String[] runtimeInit = { System.lineSeparator() };
@NeverInline
private static void staticNonConstants() {