Enum unboxing: Support hashCode
Bug: 157112269
Change-Id: I1d299cba94f6fef5837a29db5848553b71da29d2
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 1a318c0..0d0d1bd 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -164,6 +164,7 @@
public final DexString startsWithMethodName = createString("startsWith");
public final DexString endsWithMethodName = createString("endsWith");
public final DexString equalsMethodName = createString("equals");
+ public final DexString hashCodeMethodName = createString("hashCode");
public final DexString equalsIgnoreCaseMethodName = createString("equalsIgnoreCase");
public final DexString contentEqualsMethodName = createString("contentEquals");
public final DexString indexOfMethodName = createString("indexOf");
@@ -1269,6 +1270,7 @@
public final DexMethod toString;
public final DexMethod compareTo;
public final DexMethod equals;
+ public final DexMethod hashCode;
public final DexMethod constructor =
createMethod(enumType, createProto(voidType, stringType, intType), constructorMethodName);
@@ -1309,6 +1311,8 @@
equalsMethodName,
booleanDescriptor,
new DexString[] {objectDescriptor});
+ hashCode =
+ createMethod(enumDescriptor, hashCodeMethodName, intDescriptor, DexString.EMPTY_ARRAY);
}
public boolean isValuesMethod(DexMethod method, DexClass enumClass) {
@@ -1495,7 +1499,7 @@
createMethod(stringDescriptor, compareToIgnoreCaseMethodName, intDescriptor,
needsOneString);
- hashCode = createMethod(stringType, createProto(intType), "hashCode");
+ hashCode = createMethod(stringType, createProto(intType), hashCodeMethodName);
valueOf = createMethod(
stringDescriptor, valueOfMethodName, stringDescriptor, needsOneObject);
toString = createMethod(
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 379fc28..3239c8c 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
@@ -457,6 +457,8 @@
return Reason.ELIGIBLE;
} else if (singleTarget == factory.enumMethods.ordinal) {
return Reason.ELIGIBLE;
+ } else if (singleTarget == factory.enumMethods.hashCode) {
+ return Reason.ELIGIBLE;
} else if (singleTarget == factory.enumMethods.constructor) {
// Enum constructor call is allowed only if first call of an enum initializer.
if (code.method().isInstanceInitializer()
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index 541cd92..1832a2a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -129,7 +129,8 @@
DexMethod invokedMethod = invokeMethod.getInvokedMethod();
DexType enumType = getEnumTypeOrNull(invokeMethod.getReceiver(), convertedEnums);
if (enumType != null) {
- if (invokedMethod == factory.enumMethods.ordinal) {
+ if (invokedMethod == factory.enumMethods.ordinal
+ || invokedMethod == factory.enumMethods.hashCode) {
replaceEnumInvoke(
iterator, invokeMethod, ordinalUtilityMethod, m -> synthesizeOrdinalMethod());
continue;
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/OrdinalHashCodeEnumUnboxingTest.java
similarity index 88%
rename from src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingTest.java
rename to src/test/java/com/android/tools/r8/enumunboxing/OrdinalHashCodeEnumUnboxingTest.java
index b388ed7..8bd41c3 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/OrdinalHashCodeEnumUnboxingTest.java
@@ -14,7 +14,7 @@
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
-public class OrdinalEnumUnboxingTest extends EnumUnboxingTestBase {
+public class OrdinalHashCodeEnumUnboxingTest extends EnumUnboxingTestBase {
private static final Class<?> ENUM_CLASS = MyEnum.class;
@@ -27,7 +27,7 @@
return enumUnboxingTestParameters();
}
- public OrdinalEnumUnboxingTest(
+ public OrdinalHashCodeEnumUnboxingTest(
TestParameters parameters, boolean enumValueOptimization, KeepRule enumKeepRules) {
this.parameters = parameters;
this.enumValueOptimization = enumValueOptimization;
@@ -36,7 +36,7 @@
@Test
public void testEnumUnboxing() throws Exception {
- Class<Ordinal> classToTest = Ordinal.class;
+ Class<?> classToTest = OrdinalHashCode.class;
R8TestRunResult run =
testForR8(parameters.getBackend())
.addProgramClasses(classToTest, ENUM_CLASS)
@@ -61,11 +61,13 @@
C
}
- static class Ordinal {
+ static class OrdinalHashCode {
public static void main(String[] args) {
System.out.println(MyEnum.A.ordinal());
System.out.println(0);
+ System.out.println(MyEnum.A.hashCode());
+ System.out.println(0);
}
}
}