Revert "More detailed enum unboxing diagnostics for debugging"
This reverts commit 23964b1f670c52c715dd0533594154aedaf21fac.
Reason for revert: Failures
Change-Id: Ibbb087d255f7c730761b37df2f9a49c010f2de88
diff --git a/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java b/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
index 58862d7..6ab995d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
@@ -48,10 +48,6 @@
return getReference().asMethodReference();
}
- public DexType getParameter(int index) {
- return getReference().getParameter(index);
- }
-
public DexTypeList getParameters() {
return getReference().getParameters();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index 6fe8c6f..5793ec1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -25,7 +25,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.conversion.DexBuilder;
-import com.android.tools.r8.utils.BooleanUtils;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.Opcodes;
@@ -161,11 +160,6 @@
return arguments().get(index);
}
- public Value getArgumentForParameter(int index) {
- int offset = BooleanUtils.intValue(!isInvokeStatic());
- return getArgument(index + offset);
- }
-
public Value getFirstArgument() {
return getArgument(0);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 3a65557..b637199 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -77,13 +77,6 @@
import com.android.tools.r8.ir.optimize.enums.EnumInstanceFieldData.EnumInstanceFieldOrdinalData;
import com.android.tools.r8.ir.optimize.enums.EnumInstanceFieldData.EnumInstanceFieldUnknownData;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.IllegalInvokeWithImpreciseParameterTypeReason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingContentsForEnumValuesArrayReason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingEnumStaticFieldValuesReason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingInstanceFieldValueForEnumInstanceReason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingObjectStateForEnumInstanceReason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.UnsupportedInstanceFieldValueForEnumInstanceReason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.UnsupportedLibraryInvokeReason;
import com.android.tools.r8.ir.optimize.info.MutableFieldOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback.OptimizationInfoFixer;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
@@ -91,6 +84,7 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.shaking.KeepInfoCollection;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.collections.ImmutableInt2ReferenceSortedMap;
@@ -344,7 +338,7 @@
if (singleTarget != null && singleTarget.getReference() == factory.enumMembers.valueOf) {
// The name data is required for the correct mapping from the enum name to the ordinal in
// the valueOf utility method.
- addRequiredNameData(enumClass);
+ addRequiredNameData(enumType);
continue;
}
}
@@ -354,9 +348,9 @@
eligibleEnums.add(enumType);
}
- private void addRequiredNameData(DexProgramClass enumClass) {
+ private void addRequiredNameData(DexType enumType) {
enumUnboxingCandidatesInfo.addRequiredEnumInstanceFieldData(
- enumClass, factory.enumMembers.nameField);
+ enumType, factory.enumMembers.nameField);
}
private boolean isUnboxableNameMethod(DexMethod method) {
@@ -513,9 +507,10 @@
private EnumDataMap analyzeEnumInstances() {
ImmutableMap.Builder<DexType, EnumData> builder = ImmutableMap.builder();
enumUnboxingCandidatesInfo.forEachCandidateAndRequiredInstanceFieldData(
- (enumClass, instanceFields) -> {
- EnumData data = buildData(enumClass, instanceFields);
+ (enumClass, fields) -> {
+ EnumData data = buildData(enumClass, fields);
if (data == null) {
+ markEnumAsUnboxable(Reason.MISSING_INSTANCE_FIELD_DATA, enumClass);
return;
}
if (!debugLogEnabled || !debugLogs.containsKey(enumClass.getType())) {
@@ -526,7 +521,7 @@
return new EnumDataMap(builder.build());
}
- private EnumData buildData(DexProgramClass enumClass, Set<DexField> instanceFields) {
+ private EnumData buildData(DexProgramClass enumClass, Set<DexField> fields) {
// This map holds all the accessible fields to their unboxed value, so we can remap the field
// read to the unboxed value.
ImmutableMap.Builder<DexField, Integer> unboxedValues = ImmutableMap.builder();
@@ -540,7 +535,6 @@
EnumStaticFieldValues enumStaticFieldValues = staticFieldValuesMap.get(enumClass.type);
if (enumStaticFieldValues == null) {
- reportFailure(enumClass, new MissingEnumStaticFieldValuesReason());
return null;
}
@@ -556,16 +550,10 @@
continue;
}
// We could not track the content of that field. We bail out.
- reportFailure(
- enumClass, new MissingObjectStateForEnumInstanceReason(staticField.getReference()));
return null;
}
OptionalInt optionalOrdinal = getOrdinal(enumState);
if (!optionalOrdinal.isPresent()) {
- reportFailure(
- enumClass,
- new MissingInstanceFieldValueForEnumInstanceReason(
- staticField.getReference(), factory.enumMembers.ordinalField));
return null;
}
int ordinal = optionalOrdinal.getAsInt();
@@ -582,8 +570,6 @@
// We could not track the content of that field. We bail out.
// We could not track the content of that field, and the field could be a values field.
// We conservatively bail out.
- reportFailure(
- enumClass, new MissingContentsForEnumValuesArrayReason(staticField.getReference()));
return null;
}
assert valuesState.isEnumValuesObjectState();
@@ -614,41 +600,25 @@
// The ordinalToObjectState map may have holes at this point, if some enum instances are never
// used ($VALUES unused or removed, and enum instance field unused or removed), it contains
// only data for reachable enum instance, that is what we're interested in.
- ImmutableMap<DexField, EnumInstanceFieldKnownData> instanceFieldsData =
- computeRequiredEnumInstanceFieldsData(enumClass, instanceFields, ordinalToObjectState);
- if (instanceFieldsData == null) {
- return null;
+ ImmutableMap.Builder<DexField, EnumInstanceFieldKnownData> instanceFieldBuilder =
+ ImmutableMap.builder();
+ for (DexField instanceField : fields) {
+ EnumInstanceFieldData fieldData =
+ computeEnumFieldData(instanceField, enumClass, ordinalToObjectState);
+ if (fieldData.isUnknown()) {
+ return null;
+ }
+ instanceFieldBuilder.put(instanceField, fieldData.asEnumFieldKnownData());
}
return new EnumData(
- instanceFieldsData,
+ instanceFieldBuilder.build(),
unboxedValues.build(),
valuesField.build(),
valuesContents == null ? EnumData.INVALID_VALUES_SIZE : valuesContents.getEnumValuesSize());
}
- private ImmutableMap<DexField, EnumInstanceFieldKnownData> computeRequiredEnumInstanceFieldsData(
- DexProgramClass enumClass,
- Set<DexField> instanceFields,
- Int2ReferenceMap<ObjectState> ordinalToObjectState) {
- ImmutableMap.Builder<DexField, EnumInstanceFieldKnownData> builder = ImmutableMap.builder();
- for (DexField instanceField : instanceFields) {
- EnumInstanceFieldData fieldData =
- computeRequiredEnumInstanceFieldData(instanceField, enumClass, ordinalToObjectState);
- if (fieldData.isUnknown()) {
- if (!debugLogEnabled) {
- return null;
- }
- builder = null;
- }
- if (builder != null) {
- builder.put(instanceField, fieldData.asEnumFieldKnownData());
- }
- }
- return builder != null ? builder.build() : null;
- }
-
- private EnumInstanceFieldData computeRequiredEnumInstanceFieldData(
+ private EnumInstanceFieldData computeEnumFieldData(
DexField instanceField,
DexProgramClass enumClass,
Int2ReferenceMap<ObjectState> ordinalToObjectState) {
@@ -661,15 +631,7 @@
for (Integer ordinal : ordinalToObjectState.keySet()) {
ObjectState state = ordinalToObjectState.get(ordinal);
AbstractValue fieldValue = state.getAbstractFieldValue(encodedInstanceField);
- if (!fieldValue.isSingleValue()) {
- reportFailure(
- enumClass, new MissingInstanceFieldValueForEnumInstanceReason(ordinal, instanceField));
- return EnumInstanceFieldUnknownData.getInstance();
- }
if (!(fieldValue.isSingleNumberValue() || fieldValue.isSingleStringValue())) {
- reportFailure(
- enumClass,
- new UnsupportedInstanceFieldValueForEnumInstanceReason(ordinal, instanceField));
return EnumInstanceFieldUnknownData.getInstance();
}
data.put(ordinalToUnboxedInt(ordinal), fieldValue);
@@ -1134,7 +1096,7 @@
Value enumValue) {
assert instanceGet.getField().holder == enumClass.type;
DexField field = instanceGet.getField();
- enumUnboxingCandidatesInfo.addRequiredEnumInstanceFieldData(enumClass, field);
+ enumUnboxingCandidatesInfo.addRequiredEnumInstanceFieldData(enumClass.type, field);
return Reason.ELIGIBLE;
}
@@ -1156,11 +1118,10 @@
if (singleTarget == null) {
return Reason.INVALID_INVOKE;
}
- DexMethod singleTargetReference = singleTarget.getReference();
- DexClass targetHolder = singleTarget.getHolder();
- if (targetHolder.isProgramClass()) {
- if (targetHolder.isEnum() && singleTarget.getDefinition().isInstanceInitializer()) {
- if (code.context().getHolder() == targetHolder && code.method().isClassInitializer()) {
+ DexClass dexClass = singleTarget.getHolder();
+ if (dexClass.isProgramClass()) {
+ if (dexClass.isEnum() && singleTarget.getDefinition().isInstanceInitializer()) {
+ if (code.method().getHolderType() == dexClass.type && code.method().isClassInitializer()) {
// The enum instance initializer is allowed to be called only from the enum clinit.
return Reason.ELIGIBLE;
} else {
@@ -1169,28 +1130,28 @@
}
// Check that the enum-value only flows into parameters whose type exactly matches the
// enum's type.
- for (int i = 0; i < singleTarget.getParameters().size(); i++) {
- if (invoke.getArgumentForParameter(i) == enumValue
- && singleTarget.getParameter(i).toBaseType(factory) != enumClass.getType()) {
- return new IllegalInvokeWithImpreciseParameterTypeReason(singleTargetReference);
+ int offset = BooleanUtils.intValue(!singleTarget.getDefinition().isStatic());
+ for (int i = 0; i < singleTarget.getReference().getParameters().size(); i++) {
+ if (invoke.getArgument(offset + i) == enumValue) {
+ if (singleTarget.getReference().getParameter(i).toBaseType(factory) != enumClass.type) {
+ return Reason.GENERIC_INVOKE;
+ }
}
}
if (invoke.isInvokeMethodWithReceiver()) {
Value receiver = invoke.asInvokeMethodWithReceiver().getReceiver();
- if (receiver == enumValue && targetHolder.isInterface()) {
+ if (receiver == enumValue && dexClass.isInterface()) {
return Reason.DEFAULT_METHOD_INVOKE;
}
}
return Reason.ELIGIBLE;
}
-
- if (targetHolder.isClasspathClass()) {
- return Reason.INVALID_INVOKE_CLASSPATH;
+ if (dexClass.isClasspathClass()) {
+ return Reason.INVALID_INVOKE;
}
-
- assert targetHolder.isLibraryClass();
-
- if (targetHolder.getType() != factory.enumType) {
+ assert dexClass.isLibraryClass();
+ DexMethod singleTargetReference = singleTarget.getReference();
+ if (dexClass.type != factory.enumType) {
// System.identityHashCode(Object) is supported for proto enums.
// Object#getClass without outValue and Objects.requireNonNull are supported since R8
// rewrites explicit null checks to such instructions.
@@ -1198,7 +1159,7 @@
return Reason.ELIGIBLE;
}
if (singleTargetReference == factory.stringMembers.valueOf) {
- addRequiredNameData(enumClass);
+ addRequiredNameData(enumClass.type);
return Reason.ELIGIBLE;
}
if (singleTargetReference == factory.objectMembers.getClass
@@ -1210,7 +1171,7 @@
|| singleTargetReference == factory.objectsMethods.requireNonNullWithMessage) {
return Reason.ELIGIBLE;
}
- return new UnsupportedLibraryInvokeReason(singleTargetReference);
+ return Reason.UNSUPPORTED_LIBRARY_CALL;
}
// TODO(b/147860220): EnumSet and EnumMap may be interesting to model.
if (singleTargetReference == factory.enumMembers.compareTo) {
@@ -1220,7 +1181,7 @@
} else if (singleTargetReference == factory.enumMembers.nameMethod
|| singleTargetReference == factory.enumMembers.toString) {
assert invoke.asInvokeMethodWithReceiver().getReceiver() == enumValue;
- addRequiredNameData(enumClass);
+ addRequiredNameData(enumClass.type);
return Reason.ELIGIBLE;
} else if (singleTargetReference == factory.enumMembers.ordinalMethod) {
return Reason.ELIGIBLE;
@@ -1228,11 +1189,12 @@
return Reason.ELIGIBLE;
} else if (singleTargetReference == factory.enumMembers.constructor) {
// Enum constructor call is allowed only if called from an enum initializer.
- if (code.method().isInstanceInitializer() && code.context().getHolder() == enumClass) {
+ if (code.method().isInstanceInitializer()
+ && code.method().getHolderType() == enumClass.type) {
return Reason.ELIGIBLE;
}
}
- return new UnsupportedLibraryInvokeReason(singleTargetReference);
+ return Reason.UNSUPPORTED_LIBRARY_CALL;
}
// Return is used for valueOf methods.
@@ -1309,27 +1271,24 @@
sb.append(System.lineSeparator());
// Print information about how often a given Reason kind prevents enum unboxing.
- Object2IntMap<Object> reasonKindCount = new Object2IntOpenHashMap<>();
+ Object2IntMap<Reason> reasonCount = new Object2IntOpenHashMap<>();
debugLogs.forEach(
(type, reasons) ->
- reasons.forEach(
- reason ->
- reasonKindCount.put(reason.getKind(), reasonKindCount.getInt(reason) + 1)));
- List<Object> differentReasonKinds = new ArrayList<>(reasonKindCount.keySet());
- differentReasonKinds.sort(
- (reasonKind, other) -> {
- int freq = reasonKindCount.getInt(reasonKind) - reasonKindCount.getInt(other);
- return freq != 0
- ? freq
- : System.identityHashCode(reasonKind) - System.identityHashCode(other);
+ reasons.forEach(reason -> reasonCount.put(reason, reasonCount.getInt(reason) + 1)));
+ List<Reason> differentReasons = new ArrayList<>(reasonCount.keySet());
+ differentReasons.sort(
+ (x, y) -> {
+ int freq = reasonCount.getInt(x) - reasonCount.getInt(y);
+ return freq != 0 ? freq : System.identityHashCode(x) - System.identityHashCode(y);
});
- differentReasonKinds.forEach(
- reasonKind ->
- sb.append(reasonKind)
- .append(" (")
- .append(reasonKindCount.getInt(reasonKind))
- .append(")")
- .append(System.lineSeparator()));
+ differentReasons.forEach(
+ x -> {
+ sb.append(x)
+ .append(" (")
+ .append(reasonCount.getInt(x))
+ .append(")")
+ .append(System.lineSeparator());
+ });
reporter.info(new StringDiagnostic(sb.toString()));
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
index 62b05a9..c45e71a9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason;
-import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.UnsupportedStaticFieldReason;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.KeepInfoCollection;
@@ -71,6 +70,9 @@
result = false;
}
if (!enumHasBasicStaticFields(clazz)) {
+ if (!enumUnboxer.reportFailure(clazz, Reason.UNEXPECTED_STATIC_FIELD)) {
+ return false;
+ }
result = false;
}
return result;
@@ -79,37 +81,32 @@
// The enum should have the $VALUES static field and only fields directly referencing the enum
// instances.
private boolean enumHasBasicStaticFields(DexProgramClass clazz) {
- boolean result = true;
for (DexEncodedField staticField : clazz.staticFields()) {
- if (isEnumField(staticField, clazz)) {
+ if (isEnumField(staticField, clazz.type)) {
// Enum field, valid, do nothing.
- } else if (matchesValuesField(staticField, clazz, factory)) {
+ } else if (matchesValuesField(staticField, clazz.type, factory)) {
// Field $VALUES, valid, do nothing.
} else if (appView.appInfo().isFieldRead(staticField)) {
// Only non read static fields are valid, and they are assumed unused.
- if (!enumUnboxer.reportFailure(
- clazz, new UnsupportedStaticFieldReason(staticField.getReference()))) {
- return false;
- }
- result = false;
+ return false;
}
}
- return result;
+ return true;
}
- static boolean isEnumField(DexEncodedField staticField, DexProgramClass enumClass) {
- return staticField.getType() == enumClass.getType()
- && staticField.isEnum()
- && staticField.isFinal();
+ static boolean isEnumField(DexEncodedField staticField, DexType enumType) {
+ return staticField.getReference().type == enumType
+ && staticField.accessFlags.isEnum()
+ && staticField.accessFlags.isFinal();
}
static boolean matchesValuesField(
- DexEncodedField staticField, DexProgramClass enumClass, DexItemFactory factory) {
- return staticField.getType().isArrayType()
- && staticField.getType().toArrayElementType(factory) == enumClass.getType()
- && staticField.isSynthetic()
- && staticField.isFinal()
- && staticField.getName() == factory.enumValuesFieldName;
+ DexEncodedField staticField, DexType enumType, DexItemFactory factory) {
+ return staticField.getReference().type.isArrayType()
+ && staticField.getReference().type.toArrayElementType(factory) == enumType
+ && staticField.accessFlags.isSynthetic()
+ && staticField.accessFlags.isFinal()
+ && staticField.getReference().name == factory.enumValuesFieldName;
}
private void removeEnumsInAnnotations() {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java
index 7d85b8d..f36474d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateInfoCollection.java
@@ -81,11 +81,11 @@
info.addMethodDependency(programMethod);
}
- public void addRequiredEnumInstanceFieldData(DexProgramClass enumClass, DexField field) {
+ public void addRequiredEnumInstanceFieldData(DexType enumType, DexField field) {
// The enumType may be removed concurrently map from enumTypeToInfo. It means in that
// case the enum is no longer a candidate, and dependencies don't need to be recorded
// anymore.
- EnumUnboxingCandidateInfo info = enumTypeToInfo.get(enumClass.getType());
+ EnumUnboxingCandidateInfo info = enumTypeToInfo.get(enumType);
if (info == null) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/eligibility/Reason.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/eligibility/Reason.java
index 5aef5cc..2cd2098 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/eligibility/Reason.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/eligibility/Reason.java
@@ -4,238 +4,46 @@
package com.android.tools.r8.ir.optimize.enums.eligibility;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexMethod;
-import com.google.common.collect.ImmutableList;
-
-public abstract class Reason {
- public static final Reason ELIGIBLE = new StringReason("ELIGIBLE");
- public static final Reason ACCESSIBILITY = new StringReason("ACCESSIBILITY");
- public static final Reason ANNOTATION = new StringReason("ANNOTATION");
- public static final Reason PINNED = new StringReason("PINNED");
- public static final Reason DOWN_CAST = new StringReason("DOWN_CAST");
- public static final Reason SUBTYPES = new StringReason("SUBTYPES");
- public static final Reason MANY_INSTANCE_FIELDS = new StringReason("MANY_INSTANCE_FIELDS");
- public static final Reason DEFAULT_METHOD_INVOKE = new StringReason("DEFAULT_METHOD_INVOKE");
- public static final Reason UNRESOLVABLE_FIELD = new StringReason("UNRESOLVABLE_FIELD");
- public static final Reason CONST_CLASS = new StringReason("CONST_CLASS");
- public static final Reason INVALID_PHI = new StringReason("INVALID_PHI");
- public static final Reason NO_INIT = new StringReason("NO_INIT");
- public static final Reason INVALID_INIT = new StringReason("INVALID_INIT");
- public static final Reason INVALID_CLINIT = new StringReason("INVALID_CLINIT");
- public static final Reason INVALID_INVOKE = new StringReason("INVALID_INVOKE");
- public static final Reason INVALID_INVOKE_CLASSPATH =
- new StringReason("INVALID_INVOKE_CLASSPATH");
- public static final Reason INVALID_INVOKE_ON_ARRAY = new StringReason("INVALID_INVOKE_ON_ARRAY");
- public static final Reason IMPLICIT_UP_CAST_IN_RETURN =
- new StringReason("IMPLICIT_UP_CAST_IN_RETURN");
+public class Reason {
+ public static final Reason ELIGIBLE = new Reason("ELIGIBLE");
+ public static final Reason ACCESSIBILITY = new Reason("ACCESSIBILITY");
+ public static final Reason ANNOTATION = new Reason("ANNOTATION");
+ public static final Reason PINNED = new Reason("PINNED");
+ public static final Reason DOWN_CAST = new Reason("DOWN_CAST");
+ public static final Reason SUBTYPES = new Reason("SUBTYPES");
+ public static final Reason MANY_INSTANCE_FIELDS = new Reason("MANY_INSTANCE_FIELDS");
+ public static final Reason GENERIC_INVOKE = new Reason("GENERIC_INVOKE");
+ public static final Reason DEFAULT_METHOD_INVOKE = new Reason("DEFAULT_METHOD_INVOKE");
+ public static final Reason UNEXPECTED_STATIC_FIELD = new Reason("UNEXPECTED_STATIC_FIELD");
+ public static final Reason UNRESOLVABLE_FIELD = new Reason("UNRESOLVABLE_FIELD");
+ public static final Reason CONST_CLASS = new Reason("CONST_CLASS");
+ public static final Reason INVALID_PHI = new Reason("INVALID_PHI");
+ public static final Reason NO_INIT = new Reason("NO_INIT");
+ public static final Reason INVALID_INIT = new Reason("INVALID_INIT");
+ public static final Reason INVALID_CLINIT = new Reason("INVALID_CLINIT");
+ public static final Reason INVALID_INVOKE = new Reason("INVALID_INVOKE");
+ public static final Reason INVALID_INVOKE_ON_ARRAY = new Reason("INVALID_INVOKE_ON_ARRAY");
+ public static final Reason IMPLICIT_UP_CAST_IN_RETURN = new Reason("IMPLICIT_UP_CAST_IN_RETURN");
+ public static final Reason UNSUPPORTED_LIBRARY_CALL = new Reason("UNSUPPORTED_LIBRARY_CALL");
public static final Reason MISSING_INSTANCE_FIELD_DATA =
- new StringReason("MISSING_INSTANCE_FIELD_DATA");
- public static final Reason INVALID_FIELD_PUT = new StringReason("INVALID_FIELD_PUT");
- public static final Reason INVALID_ARRAY_PUT = new StringReason("INVALID_ARRAY_PUT");
- public static final Reason TYPE_MISMATCH_FIELD_PUT = new StringReason("TYPE_MISMATCH_FIELD_PUT");
- public static final Reason INVALID_IF_TYPES = new StringReason("INVALID_IF_TYPES");
+ new Reason("MISSING_INSTANCE_FIELD_DATA");
+ public static final Reason INVALID_FIELD_PUT = new Reason("INVALID_FIELD_PUT");
+ public static final Reason INVALID_ARRAY_PUT = new Reason("INVALID_ARRAY_PUT");
+ public static final Reason TYPE_MISMATCH_FIELD_PUT = new Reason("TYPE_MISMATCH_FIELD_PUT");
+ public static final Reason INVALID_IF_TYPES = new Reason("INVALID_IF_TYPES");
public static final Reason ENUM_METHOD_CALLED_WITH_NULL_RECEIVER =
- new StringReason("ENUM_METHOD_CALLED_WITH_NULL_RECEIVER");
+ new Reason("ENUM_METHOD_CALLED_WITH_NULL_RECEIVER");
public static final Reason OTHER_UNSUPPORTED_INSTRUCTION =
- new StringReason("OTHER_UNSUPPORTED_INSTRUCTION");
+ new Reason("OTHER_UNSUPPORTED_INSTRUCTION");
- public abstract Object getKind();
+ private final String message;
+
+ public Reason(String message) {
+ this.message = message;
+ }
@Override
- public abstract String toString();
-
- public static class StringReason extends Reason {
-
- private final String message;
-
- public StringReason(String message) {
- this.message = message;
- }
-
- @Override
- public Object getKind() {
- return this;
- }
-
- @Override
- public String toString() {
- return message;
- }
- }
-
- public static class IllegalInvokeWithImpreciseParameterTypeReason extends Reason {
-
- private final DexMethod invokedMethod;
-
- public IllegalInvokeWithImpreciseParameterTypeReason(DexMethod invokedMethod) {
- this.invokedMethod = invokedMethod;
- }
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- return "IllegalInvokeWithImpreciseParameterType(" + invokedMethod.toSourceString() + ")";
- }
- }
-
- public static class MissingEnumStaticFieldValuesReason extends Reason {
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- return "MissingEnumStaticFieldValues";
- }
- }
-
- public static class MissingContentsForEnumValuesArrayReason extends Reason {
-
- private final DexField valuesField;
-
- public MissingContentsForEnumValuesArrayReason(DexField valuesField) {
- this.valuesField = valuesField;
- }
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- return "MissingContentsForEnumValuesArray(" + valuesField.toSourceString() + ")";
- }
- }
-
- public static class MissingInstanceFieldValueForEnumInstanceReason extends Reason {
-
- private final DexField enumField;
- private final int ordinal;
- private final DexField instanceField;
-
- public MissingInstanceFieldValueForEnumInstanceReason(
- DexField enumField, DexField instanceField) {
- this.enumField = enumField;
- this.ordinal = -1;
- this.instanceField = instanceField;
- }
-
- public MissingInstanceFieldValueForEnumInstanceReason(int ordinal, DexField instanceField) {
- this.enumField = null;
- this.ordinal = ordinal;
- this.instanceField = instanceField;
- }
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- if (enumField != null) {
- return "MissingInstanceFieldValueForEnumInstance(enum field="
- + enumField.toSourceString()
- + ", instance field="
- + instanceField.toSourceString()
- + ")";
- }
- assert ordinal >= 0;
- return "MissingInstanceFieldValueForEnumInstance(ordinal="
- + ordinal
- + ", instance field="
- + instanceField.toSourceString()
- + ")";
- }
- }
-
- public static class MissingObjectStateForEnumInstanceReason extends Reason {
-
- private final DexField enumField;
-
- public MissingObjectStateForEnumInstanceReason(DexField enumField) {
- this.enumField = enumField;
- }
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- return "MissingObjectStateForEnumInstance(" + enumField + ")";
- }
- }
-
- public static class UnsupportedInstanceFieldValueForEnumInstanceReason extends Reason {
-
- private final int ordinal;
- private final DexField instanceField;
-
- public UnsupportedInstanceFieldValueForEnumInstanceReason(int ordinal, DexField instanceField) {
- this.ordinal = ordinal;
- this.instanceField = instanceField;
- }
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- return "UnsupportedInstanceFieldValueForEnumInstance(ordinal="
- + ordinal
- + ", instance field="
- + instanceField.toSourceString()
- + ")";
- }
- }
-
- public static class UnsupportedLibraryInvokeReason extends Reason {
-
- private final DexMethod invokedMethod;
-
- public UnsupportedLibraryInvokeReason(DexMethod invokedMethod) {
- this.invokedMethod = invokedMethod;
- }
-
- @Override
- public Object getKind() {
- return ImmutableList.of(getClass(), invokedMethod);
- }
-
- @Override
- public String toString() {
- return "UnsupportedLibraryInvoke(" + invokedMethod.toSourceString() + ")";
- }
- }
-
- public static class UnsupportedStaticFieldReason extends Reason {
-
- private final DexField field;
-
- public UnsupportedStaticFieldReason(DexField field) {
- this.field = field;
- }
-
- @Override
- public Object getKind() {
- return getClass();
- }
-
- @Override
- public String toString() {
- return "UnsupportedStaticField(" + field.toSourceString() + ")";
- }
+ public String toString() {
+ return message;
}
}