Enum unboxing: parametrize tests
- Add enumValueOpt parameter, since the
enumValueOptimization have important side
effects on enumUnboxing.
- Add enumKeepRules parameter, since big
apps such as Youtube do not have these
keep rules but all apps on studio have it.
- Fix a bug where EnumUnboxing would raise
an assertion error when the input was
invalid (don't unbox instead).
Bug: 147860220
Change-Id: I6a7562ad218fdacb82412ca50dbcc15f7c14db19
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 5d737b5..b3a25d0 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
@@ -143,7 +143,13 @@
assert enumClass != null;
DexEncodedMethod initializer = enumClass.lookupDirectMethod(factory.enumMethods.constructor);
- assert initializer != null;
+ if (initializer == null) {
+ // This case typically happens when a programmer uses EnumSet/EnumMap without using the
+ // enum keep rules. The code is incorrect in this case (EnumSet/EnumMap won't work).
+ // We bail out.
+ markEnumAsUnboxable(Reason.NO_INIT, enumClass);
+ continue;
+ }
if (initializer.getOptimizationInfo().mayHaveSideEffects()) {
markEnumAsUnboxable(Reason.INVALID_INIT, enumClass);
continue;
@@ -325,6 +331,7 @@
VIRTUAL_METHOD,
UNEXPECTED_DIRECT_METHOD,
INVALID_PHI,
+ NO_INIT,
INVALID_INIT,
INVALID_CLINIT,
INVALID_INVOKE,
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/ComparisonEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/ComparisonEnumUnboxingAnalysisTest.java
index ddcb725..a15dc08 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/ComparisonEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/ComparisonEnumUnboxingAnalysisTest.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -19,16 +19,22 @@
@RunWith(Parameterized.class)
public class ComparisonEnumUnboxingAnalysisTest extends EnumUnboxingTestBase {
- private final TestParameters parameters;
- private final Class<?>[] INPUTS = new Class<?>[] {NullCheck.class, EnumComparison.class};
+ private static final Class<?>[] INPUTS = new Class<?>[] {NullCheck.class, EnumComparison.class};
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public ComparisonEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public ComparisonEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
@Test
@@ -37,9 +43,9 @@
testForR8(parameters.getBackend())
.addInnerClasses(ComparisonEnumUnboxingAnalysisTest.class)
.addKeepMainRules(INPUTS)
- .addKeepRules(KEEP_ENUM)
.enableInliningAnnotations()
- .addOptionsModification(this::enableEnumOptions)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java
index 332ad2e..b7ebc83 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java
@@ -10,9 +10,9 @@
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessages;
-import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import java.util.List;
@@ -34,8 +34,9 @@
}
}
- void enableEnumOptions(InternalOptions options) {
+ void enableEnumOptions(InternalOptions options, boolean enumValueOptimization) {
options.enableEnumUnboxing = true;
+ options.enableEnumValueOptimization = enumValueOptimization;
options.testing.enableEnumUnboxingDebugLogs = true;
}
@@ -55,12 +56,15 @@
diagnostic.getDiagnosticMessage().contains(enumClass.getSimpleName()));
}
- static TestParametersCollection enumUnboxingTestParameters() {
- return getTestParameters()
- .withCfRuntime(CfVm.JDK9)
- .withDexRuntime(DexVm.Version.first())
- .withDexRuntime(DexVm.Version.last())
- .withAllApiLevels()
- .build();
+ static List<Object[]> enumUnboxingTestParameters() {
+ return buildParameters(
+ getTestParameters()
+ .withCfRuntime(CfVm.JDK9)
+ .withDexRuntime(DexVm.Version.first())
+ .withDexRuntime(DexVm.Version.last())
+ .withAllApiLevels()
+ .build(),
+ BooleanUtils.values(),
+ BooleanUtils.values());
}
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingAnalysisTest.java
index 9c4872f..c0eeaf4 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingAnalysisTest.java
@@ -12,13 +12,13 @@
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.enumunboxing.FailingEnumUnboxingAnalysisTest.EnumInstanceFieldMain.EnumInstanceField;
import com.android.tools.r8.enumunboxing.FailingEnumUnboxingAnalysisTest.EnumInterfaceMain.EnumInterface;
import com.android.tools.r8.enumunboxing.FailingEnumUnboxingAnalysisTest.EnumStaticFieldMain.EnumStaticField;
import com.android.tools.r8.enumunboxing.FailingEnumUnboxingAnalysisTest.EnumStaticMethodMain.EnumStaticMethod;
import com.android.tools.r8.enumunboxing.FailingEnumUnboxingAnalysisTest.EnumVirtualMethodMain.EnumVirtualMethod;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -36,14 +36,19 @@
};
private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public FailingEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public FailingEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
@Test
@@ -57,8 +62,8 @@
r8FullTestBuilder
.noTreeShaking() // Disabled to avoid merging Itf into EnumInterface.
.enableInliningAnnotations()
- .addKeepRules(KEEP_ENUM)
- .addOptionsModification(this::enableEnumOptions)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/FailingMethodEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/FailingMethodEnumUnboxingAnalysisTest.java
index c7ad117..944c9c3 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/FailingMethodEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/FailingMethodEnumUnboxingAnalysisTest.java
@@ -11,9 +11,9 @@
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.EnumSet;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -31,14 +31,19 @@
};
private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public FailingMethodEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public FailingMethodEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
@Test
@@ -47,13 +52,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(FailingMethodEnumUnboxingAnalysisTest.class)
.addKeepMainRules(FAILURES)
- .addKeepRules(KEEP_ENUM)
- .addOptionsModification(this::enableEnumOptions)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.enableInliningAnnotations()
- .addOptionsModification(
- // Disabled to avoid toString() being removed.
- opt -> opt.enableEnumValueOptimization = false)
.setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::assertEnumsAsExpected);
@@ -64,9 +66,14 @@
m ->
assertEnumIsBoxed(
failure.getDeclaredClasses()[0], failure.getSimpleName(), m))
- .run(parameters.getRuntime(), failure)
- .assertSuccess();
- assertLines2By2Correct(run.getStdOut());
+ .run(parameters.getRuntime(), failure);
+ if (failure == EnumSetTest.class && !enumKeepRules) {
+ // EnumSet and EnumMap cannot be used without the enumKeepRules.
+ run.assertFailure();
+ } else {
+ run.assertSuccess();
+ assertLines2By2Correct(run.getStdOut());
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/FieldPutEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/FieldPutEnumUnboxingAnalysisTest.java
index 8811ee5..daaf504 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/FieldPutEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/FieldPutEnumUnboxingAnalysisTest.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -19,17 +19,23 @@
@RunWith(Parameterized.class)
public class FieldPutEnumUnboxingAnalysisTest extends EnumUnboxingTestBase {
- private final TestParameters parameters;
private static final Class<?>[] INPUTS =
new Class<?>[] {InstanceFieldPut.class, StaticFieldPut.class};
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public FieldPutEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public FieldPutEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
@Test
@@ -38,8 +44,8 @@
testForR8(parameters.getBackend())
.addInnerClasses(FieldPutEnumUnboxingAnalysisTest.class)
.addKeepMainRules(INPUTS)
- .addKeepRules(KEEP_ENUM)
- .addOptionsModification(this::enableEnumOptions)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.enableInliningAnnotations()
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingAnalysisTest.java
index 2570a12..afd2e6a 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/OrdinalEnumUnboxingAnalysisTest.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -15,19 +15,24 @@
@RunWith(Parameterized.class)
public class OrdinalEnumUnboxingAnalysisTest extends EnumUnboxingTestBase {
- private final TestParameters parameters;
+ private static final Class<?> ENUM_CLASS = MyEnum.class;
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public OrdinalEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public OrdinalEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
- private static final Class<?> ENUM_CLASS = MyEnum.class;
-
@Test
public void testEnumUnboxing() throws Exception {
Class<Ordinal> classToTest = Ordinal.class;
@@ -35,8 +40,8 @@
testForR8(parameters.getBackend())
.addProgramClasses(classToTest, ENUM_CLASS)
.addKeepMainRule(classToTest)
- .addKeepRules(KEEP_ENUM)
- .addOptionsModification(this::enableEnumOptions)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/PhiEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/PhiEnumUnboxingAnalysisTest.java
index 2abd358..b231d32 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/PhiEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/PhiEnumUnboxingAnalysisTest.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -16,19 +16,24 @@
@RunWith(Parameterized.class)
public class PhiEnumUnboxingAnalysisTest extends EnumUnboxingTestBase {
- private final TestParameters parameters;
+ private static final Class<?> ENUM_CLASS = MyEnum.class;
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public PhiEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public PhiEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
- private static final Class<?> ENUM_CLASS = MyEnum.class;
-
@Test
public void testEnumUnboxing() throws Exception {
Class<?> classToTest = Phi.class;
@@ -36,9 +41,9 @@
testForR8(parameters.getBackend())
.addProgramClasses(classToTest, ENUM_CLASS)
.addKeepMainRule(classToTest)
- .addKeepRules(KEEP_ENUM)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
.enableInliningAnnotations()
- .addOptionsModification(this::enableEnumOptions)
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.setMinApi(parameters.getApiLevel())
.compile()
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingAnalysisTest.java b/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingAnalysisTest.java
index 53cddc6..a40dec0 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingAnalysisTest.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -16,19 +16,24 @@
@RunWith(Parameterized.class)
public class SwitchEnumUnboxingAnalysisTest extends EnumUnboxingTestBase {
- private final TestParameters parameters;
+ private static final Class<?> ENUM_CLASS = MyEnum.class;
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final boolean enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
return enumUnboxingTestParameters();
}
- public SwitchEnumUnboxingAnalysisTest(TestParameters parameters) {
+ public SwitchEnumUnboxingAnalysisTest(
+ TestParameters parameters, boolean enumValueOptimization, boolean enumKeepRules) {
this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
}
- private static final Class<?> ENUM_CLASS = MyEnum.class;
-
@Test
public void testEnumUnboxing() throws Exception {
Class<Switch> classToTest = Switch.class;
@@ -36,9 +41,9 @@
testForR8(parameters.getBackend())
.addInnerClasses(SwitchEnumUnboxingAnalysisTest.class)
.addKeepMainRule(classToTest)
- .addKeepRules(KEEP_ENUM)
+ .addKeepRules(enumKeepRules ? KEEP_ENUM : "")
.enableInliningAnnotations()
- .addOptionsModification(this::enableEnumOptions)
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
.allowDiagnosticInfoMessages()
.setMinApi(parameters.getApiLevel())
.compile()