blob: f3bb8e7871fa98e2b1003c0d1ac04ed8f6019d97 [file] [log] [blame]
// Copyright (c) 2019, 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.switches;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
public class SwitchMapCollectionWithoutStaticGetTest extends TestBase {
private final TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
public SwitchMapCollectionWithoutStaticGetTest(TestParameters parameters) {
this.parameters = parameters;
}
@Test
public void test() throws Exception {
testForR8(parameters.getBackend())
.addProgramClasses(TestClass.class, MyEnum.class)
.addProgramClassFileData(SwitchMapClassDump.dump())
.addKeepMainRule(TestClass.class)
.setMinApi(parameters.getApiLevel())
.compile()
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutputLines("Hello world!");
}
static class TestClass {
public static void main(String[] args) {
MyEnum x = System.currentTimeMillis() >= 0 ? MyEnum.A : MyEnum.B;
switch (x) {
case A:
System.out.println("Hello world!");
break;
case B:
throw new RuntimeException();
}
}
}
enum MyEnum {
A,
B
}
/**
* The following is the javac generated switch map for {@link MyEnum} with changes documented
* below.
*/
static class SwitchMapClassDump implements Opcodes {
public static byte[] dump() {
ClassWriter classWriter = new ClassWriter(0);
FieldVisitor fieldVisitor;
MethodVisitor methodVisitor;
classWriter.visit(
V1_8,
ACC_SUPER | ACC_SYNTHETIC,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$1",
null,
"java/lang/Object",
null);
classWriter.visitSource("SwitchMapCollectionWithoutStaticGetTest.java", null);
classWriter.visitOuterClass(
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest",
null,
null);
classWriter.visitInnerClass(
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$1",
null,
null,
ACC_STATIC | ACC_SYNTHETIC);
classWriter.visitInnerClass(
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest",
"MyEnum",
ACC_FINAL | ACC_STATIC | ACC_ENUM);
{
fieldVisitor =
classWriter.visitField(
ACC_FINAL | ACC_STATIC | ACC_SYNTHETIC,
"$SwitchMap$com$android$tools$r8$ir$optimize$switches$SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"[I",
null,
null);
fieldVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
Label label1 = new Label();
Label label2 = new Label();
methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/NoSuchFieldError");
Label label3 = new Label();
Label label4 = new Label();
Label label5 = new Label();
methodVisitor.visitTryCatchBlock(label3, label4, label5, "java/lang/NoSuchFieldError");
Label label6 = new Label();
methodVisitor.visitLabel(label6);
methodVisitor.visitLineNumber(52, label6);
methodVisitor.visitMethodInsn(
INVOKESTATIC,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"values",
"()[Lcom/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum;",
false);
methodVisitor.visitInsn(ARRAYLENGTH);
methodVisitor.visitIntInsn(NEWARRAY, T_INT);
methodVisitor.visitInsn(DUP); // NEW: DUP instead of GETSTATIC below.
methodVisitor.visitFieldInsn(
PUTSTATIC,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$1",
"$SwitchMap$com$android$tools$r8$ir$optimize$switches$SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"[I");
methodVisitor.visitLabel(label0);
// methodVisitor.visitFieldInsn(GETSTATIC,
// "com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$1",
// "$SwitchMap$com$android$tools$r8$ir$optimize$switches$SwitchMapCollectionWithoutStaticGetTest$MyEnum", "[I");
methodVisitor.visitFieldInsn(
GETSTATIC,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"A",
"Lcom/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum;");
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"ordinal",
"()I",
false);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitInsn(IASTORE);
methodVisitor.visitLabel(label1);
methodVisitor.visitJumpInsn(GOTO, label3);
methodVisitor.visitLabel(label2);
methodVisitor.visitFrame(
Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/NoSuchFieldError"});
methodVisitor.visitVarInsn(ASTORE, 0);
methodVisitor.visitLabel(label3);
methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
methodVisitor.visitFieldInsn(
GETSTATIC,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$1",
"$SwitchMap$com$android$tools$r8$ir$optimize$switches$SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"[I");
methodVisitor.visitFieldInsn(
GETSTATIC,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"B",
"Lcom/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum;");
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL,
"com/android/tools/r8/ir/optimize/switches/SwitchMapCollectionWithoutStaticGetTest$MyEnum",
"ordinal",
"()I",
false);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitInsn(IASTORE);
methodVisitor.visitLabel(label4);
Label label7 = new Label();
methodVisitor.visitJumpInsn(GOTO, label7);
methodVisitor.visitLabel(label5);
methodVisitor.visitFrame(
Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/NoSuchFieldError"});
methodVisitor.visitVarInsn(ASTORE, 0);
methodVisitor.visitLabel(label7);
methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(3, 1);
methodVisitor.visitEnd();
}
classWriter.visitEnd();
return classWriter.toByteArray();
}
}
}