VarHandle desugaring test of types not supported by desugaring
Bug: b/247076137
Change-Id: I4634d35f094a40d1725dc9f9c909ac3e96df88c7
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
index 112f246..849a6b4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
@@ -57,6 +57,7 @@
factory.createSynthesizedType("Ljava/lang/Long;");
factory.createSynthesizedType("Ljava/lang/RuntimeException;");
factory.createSynthesizedType("Ljava/lang/Short;");
+ factory.createSynthesizedType("Ljava/lang/UnsupportedOperationException;");
factory.createSynthesizedType("Ljava/lang/reflect/Field;");
factory.createSynthesizedType("Lsun/misc/Unsafe;");
}
@@ -521,6 +522,9 @@
CfLabel label7 = new CfLabel();
CfLabel label8 = new CfLabel();
CfLabel label9 = new CfLabel();
+ CfLabel label10 = new CfLabel();
+ CfLabel label11 = new CfLabel();
+ CfLabel label12 = new CfLabel();
return new CfCode(
method.holder,
4,
@@ -610,6 +614,107 @@
factory.classType,
factory.createString("type"))),
label7,
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.classType,
+ factory.createProto(factory.booleanType),
+ factory.createString("isPrimitive")),
+ false),
+ new CfIf(If.Type.EQ, ValueType.INT, label10),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfStaticFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/Integer;"),
+ factory.classType,
+ factory.createString("TYPE"))),
+ new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label10),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfStaticFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/Long;"),
+ factory.classType,
+ factory.createString("TYPE"))),
+ new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label10),
+ label8,
+ new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfNew(factory.stringBuilderType),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfInvoke(
+ 183,
+ factory.createMethod(
+ factory.stringBuilderType,
+ factory.createProto(factory.voidType),
+ factory.createString("<init>")),
+ false),
+ new CfConstString(factory.createString("Using a VarHandle for a field of type '")),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.stringBuilderType,
+ factory.createProto(factory.stringBuilderType, factory.stringType),
+ factory.createString("append")),
+ false),
+ new CfLoad(ValueType.OBJECT, 3),
+ label9,
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.classType,
+ factory.createProto(factory.stringType),
+ factory.createString("getName")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.stringBuilderType,
+ factory.createProto(factory.stringBuilderType, factory.stringType),
+ factory.createString("append")),
+ false),
+ new CfConstString(
+ factory.createString(
+ "' requires native VarHandle support available from Android 13. VarHandle"
+ + " desugaring only supports primitive types int and long and reference"
+ + " types.")),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.stringBuilderType,
+ factory.createProto(factory.stringBuilderType, factory.stringType),
+ factory.createString("append")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.stringBuilderType,
+ factory.createProto(factory.stringType),
+ factory.createString("toString")),
+ false),
+ new CfInvoke(
+ 183,
+ factory.createMethod(
+ factory.createType("Ljava/lang/UnsupportedOperationException;"),
+ factory.createProto(factory.voidType, factory.stringType),
+ factory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label10,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Lcom/android/tools/r8/DesugarVarHandle;")),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.initializedNonNullReference(factory.stringType),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/reflect/Field;")),
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/reflect/Field;"))
+ })),
new CfLoad(ValueType.OBJECT, 0),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceFieldRead(
@@ -640,9 +745,9 @@
factory.createType("Lcom/android/tools/r8/DesugarVarHandle;"),
factory.longType,
factory.createString("offset"))),
- label8,
+ label11,
new CfReturnVoid(),
- label9),
+ label12),
ImmutableList.of(),
ImmutableList.of());
}
diff --git a/src/test/examplesJava9/varhandle/InstanceBooleanField.java b/src/test/examplesJava9/varhandle/InstanceBooleanField.java
new file mode 100644
index 0000000..89c034a
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceBooleanField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, 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 varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceBooleanField {
+
+ private boolean field;
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testGet");
+
+ InstanceBooleanField instance = new InstanceBooleanField();
+ System.out.println(varHandle.get(instance));
+
+ // boolean and Boolean values.
+ varHandle.set(instance, true);
+ System.out.println((boolean) varHandle.get(instance));
+ varHandle.set(instance, Boolean.FALSE);
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void testCompareAndSet(VarHandle varHandle) {
+ System.out.println("testCompareAndSet");
+
+ InstanceBooleanField instance = new InstanceBooleanField();
+
+ // boolean and Boolean values.
+ varHandle.compareAndSet(instance, true, false);
+ System.out.println((boolean) varHandle.get(instance));
+ varHandle.compareAndSet(instance, false, true);
+ System.out.println((boolean) varHandle.get(instance));
+ varHandle.compareAndSet(instance, Boolean.TRUE, false);
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, false, Boolean.TRUE);
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, Boolean.TRUE, Boolean.FALSE);
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+ VarHandle varHandle;
+ try {
+ varHandle =
+ MethodHandles.lookup().findVarHandle(InstanceBooleanField.class, "field", boolean.class);
+ } catch (UnsupportedOperationException e) {
+ System.out.println("Got UnsupportedOperationException");
+ return;
+ }
+
+ testSet(varHandle);
+ testCompareAndSet(varHandle);
+ }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceByteField.java b/src/test/examplesJava9/varhandle/InstanceByteField.java
new file mode 100644
index 0000000..242df89
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceByteField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, 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 varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceByteField {
+
+ private byte field;
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testGet");
+
+ InstanceByteField instance = new InstanceByteField();
+ System.out.println(varHandle.get(instance));
+
+ // byte and Byte values.
+ varHandle.set(instance, (byte) 1);
+ System.out.println((byte) varHandle.get(instance));
+ varHandle.set(instance, Byte.valueOf((byte) 2));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void testCompareAndSet(VarHandle varHandle) {
+ System.out.println("testCompareAndSet");
+
+ InstanceByteField instance = new InstanceByteField();
+
+ // byte and Byte values.
+ varHandle.compareAndSet(instance, (byte) 1, (byte) 2);
+ System.out.println((byte) varHandle.get(instance));
+ varHandle.compareAndSet(instance, (byte) 0, (byte) 1);
+ System.out.println((byte) varHandle.get(instance));
+ varHandle.compareAndSet(instance, Byte.valueOf((byte) 1), (byte) 2);
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, (byte) 2, Byte.valueOf((byte) 3));
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, Byte.valueOf((byte) 3), Byte.valueOf((byte) 4));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+ VarHandle varHandle;
+ try {
+ varHandle =
+ MethodHandles.lookup().findVarHandle(InstanceByteField.class, "field", byte.class);
+ } catch (UnsupportedOperationException e) {
+ System.out.println("Got UnsupportedOperationException");
+ return;
+ }
+
+ testSet(varHandle);
+ testCompareAndSet(varHandle);
+ }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceDoubleField.java b/src/test/examplesJava9/varhandle/InstanceDoubleField.java
new file mode 100644
index 0000000..5b59463
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceDoubleField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, 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 varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceDoubleField {
+
+ private double field;
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testGet");
+
+ InstanceDoubleField instance = new InstanceDoubleField();
+ System.out.println(varHandle.get(instance));
+
+ // double and Double values.
+ varHandle.set(instance, 1.0);
+ System.out.println((double) varHandle.get(instance));
+ varHandle.set(instance, Double.valueOf(2));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void testCompareAndSet(VarHandle varHandle) {
+ System.out.println("testCompareAndSet");
+
+ InstanceDoubleField instance = new InstanceDoubleField();
+
+ // double and Double values.
+ varHandle.compareAndSet(instance, 1.0, 2.0);
+ System.out.println((double) varHandle.get(instance));
+ varHandle.compareAndSet(instance, 0.0, 1.0);
+ System.out.println((double) varHandle.get(instance));
+ varHandle.compareAndSet(instance, Double.valueOf(1), 2.0);
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, 2.0, Double.valueOf(3));
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, Double.valueOf(3), Double.valueOf(4));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+ VarHandle varHandle;
+ try {
+ varHandle =
+ MethodHandles.lookup().findVarHandle(InstanceDoubleField.class, "field", double.class);
+ } catch (UnsupportedOperationException e) {
+ System.out.println("Got UnsupportedOperationException");
+ return;
+ }
+
+ testSet(varHandle);
+ testCompareAndSet(varHandle);
+ }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceFloatField.java b/src/test/examplesJava9/varhandle/InstanceFloatField.java
new file mode 100644
index 0000000..06960c4
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceFloatField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, 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 varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceFloatField {
+
+ private float field;
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testGet");
+
+ InstanceFloatField instance = new InstanceFloatField();
+ System.out.println(varHandle.get(instance));
+
+ // float and Float values.
+ varHandle.set(instance, 1.0f);
+ System.out.println((float) varHandle.get(instance));
+ varHandle.set(instance, Float.valueOf(2));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void testCompareAndSet(VarHandle varHandle) {
+ System.out.println("testCompareAndSet");
+
+ InstanceFloatField instance = new InstanceFloatField();
+
+ // float and Float values.
+ varHandle.compareAndSet(instance, 1.0f, 2.0f);
+ System.out.println((float) varHandle.get(instance));
+ varHandle.compareAndSet(instance, 0.0f, 1.0f);
+ System.out.println((float) varHandle.get(instance));
+ varHandle.compareAndSet(instance, Float.valueOf(1), 2.0f);
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, 2.0f, Float.valueOf(3f));
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, Float.valueOf(3), Float.valueOf(4));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+ VarHandle varHandle;
+ try {
+ varHandle =
+ MethodHandles.lookup().findVarHandle(InstanceFloatField.class, "field", float.class);
+ } catch (UnsupportedOperationException e) {
+ System.out.println("Got UnsupportedOperationException");
+ return;
+ }
+
+ testSet(varHandle);
+ testCompareAndSet(varHandle);
+ }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceShortField.java b/src/test/examplesJava9/varhandle/InstanceShortField.java
new file mode 100644
index 0000000..7890cf2
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceShortField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, 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 varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceShortField {
+
+ private short field;
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testGet");
+
+ InstanceShortField instance = new InstanceShortField();
+ System.out.println(varHandle.get(instance));
+
+ // short and Short values.
+ varHandle.set(instance, (short) 1);
+ System.out.println((short) varHandle.get(instance));
+ varHandle.set(instance, Short.valueOf((short) 2));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void testCompareAndSet(VarHandle varHandle) {
+ System.out.println("testCompareAndSet");
+
+ InstanceShortField instance = new InstanceShortField();
+
+ // short and Short values.
+ varHandle.compareAndSet(instance, (short) 1, (short) 2);
+ System.out.println((short) varHandle.get(instance));
+ varHandle.compareAndSet(instance, (short) 0, (short) 1);
+ System.out.println((short) varHandle.get(instance));
+ varHandle.compareAndSet(instance, Short.valueOf((short) 1), (short) 2);
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, (short) 2, Short.valueOf((short) 3));
+ System.out.println(varHandle.get(instance));
+ varHandle.compareAndSet(instance, Short.valueOf((short) 3), Short.valueOf((short) 4));
+ System.out.println(varHandle.get(instance));
+ }
+
+ public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+ VarHandle varHandle;
+ try {
+ varHandle =
+ MethodHandles.lookup().findVarHandle(InstanceShortField.class, "field", short.class);
+ } catch (UnsupportedOperationException e) {
+ System.out.println("Got UnsupportedOperationException");
+ return;
+ }
+
+ testSet(varHandle);
+ testCompareAndSet(varHandle);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
new file mode 100644
index 0000000..d9fc4c4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
@@ -0,0 +1,62 @@
+// Copyright (c) 2022, 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.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceBooleanFieldTest extends VarHandleDesugaringTestBase {
+
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines(
+ "testGet",
+ "false",
+ "true",
+ "false",
+ "testCompareAndSet",
+ "false",
+ "true",
+ "false",
+ "true",
+ "false");
+
+ private static final String MAIN_CLASS = VarHandle.InstanceBooleanField.typeName();
+ private static final String JAR_ENTRY = "varhandle/InstanceBooleanField.class";
+
+ @Override
+ protected String getMainClass() {
+ return MAIN_CLASS;
+ }
+
+ @Override
+ protected String getKeepRules() {
+ return "-keep class " + getMainClass() + "{ <fields>; }";
+ }
+
+ @Override
+ protected List<String> getJarEntries() {
+ return ImmutableList.of(JAR_ENTRY);
+ }
+
+ @Override
+ protected String getExpectedOutputForReferenceImplementation() {
+ return EXPECTED_OUTPUT;
+ }
+
+ @Override
+ protected String getExpectedOutputForDesugaringImplementation() {
+ return StringUtils.lines("Got UnsupportedOperationException");
+ }
+
+ @Override
+ protected boolean getTestWithDesugaring() {
+ return true;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
new file mode 100644
index 0000000..a96b5a9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2022, 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.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceByteFieldTest extends VarHandleDesugaringTestBase {
+
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines("testGet", "0", "1", "2", "testCompareAndSet", "0", "1", "2", "3", "4");
+
+ private static final String MAIN_CLASS = VarHandle.InstanceByteField.typeName();
+ private static final String JAR_ENTRY = "varhandle/InstanceByteField.class";
+
+ @Override
+ protected String getMainClass() {
+ return MAIN_CLASS;
+ }
+
+ @Override
+ protected String getKeepRules() {
+ return "-keep class " + getMainClass() + "{ <fields>; }";
+ }
+
+ @Override
+ protected List<String> getJarEntries() {
+ return ImmutableList.of(JAR_ENTRY);
+ }
+
+ @Override
+ protected String getExpectedOutputForReferenceImplementation() {
+ return EXPECTED_OUTPUT;
+ }
+
+ @Override
+ protected String getExpectedOutputForDesugaringImplementation() {
+ return StringUtils.lines("Got UnsupportedOperationException");
+ }
+
+ @Override
+ protected boolean getTestWithDesugaring() {
+ return true;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
new file mode 100644
index 0000000..194f25f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2022, 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.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceDoubleFieldTest extends VarHandleDesugaringTestBase {
+
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines(
+ "testGet", "0.0", "1.0", "2.0", "testCompareAndSet", "0.0", "1.0", "2.0", "3.0", "4.0");
+
+ private static final String MAIN_CLASS = VarHandle.InstanceDoubleField.typeName();
+ private static final String JAR_ENTRY = "varhandle/InstanceDoubleField.class";
+
+ @Override
+ protected String getMainClass() {
+ return MAIN_CLASS;
+ }
+
+ @Override
+ protected String getKeepRules() {
+ return "-keep class " + getMainClass() + "{ <fields>; }";
+ }
+
+ @Override
+ protected List<String> getJarEntries() {
+ return ImmutableList.of(JAR_ENTRY);
+ }
+
+ @Override
+ protected String getExpectedOutputForReferenceImplementation() {
+ return EXPECTED_OUTPUT;
+ }
+
+ @Override
+ protected String getExpectedOutputForDesugaringImplementation() {
+ return StringUtils.lines("Got UnsupportedOperationException");
+ }
+
+ @Override
+ protected boolean getTestWithDesugaring() {
+ return true;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
new file mode 100644
index 0000000..457753b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2022, 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.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceFloatFieldTest extends VarHandleDesugaringTestBase {
+
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines(
+ "testGet", "0.0", "1.0", "2.0", "testCompareAndSet", "0.0", "1.0", "2.0", "3.0", "4.0");
+
+ private static final String MAIN_CLASS = VarHandle.InstanceFloatField.typeName();
+ private static final String JAR_ENTRY = "varhandle/InstanceFloatField.class";
+
+ @Override
+ protected String getMainClass() {
+ return MAIN_CLASS;
+ }
+
+ @Override
+ protected String getKeepRules() {
+ return "-keep class " + getMainClass() + "{ <fields>; }";
+ }
+
+ @Override
+ protected List<String> getJarEntries() {
+ return ImmutableList.of(JAR_ENTRY);
+ }
+
+ @Override
+ protected String getExpectedOutputForReferenceImplementation() {
+ return EXPECTED_OUTPUT;
+ }
+
+ @Override
+ protected String getExpectedOutputForDesugaringImplementation() {
+ return StringUtils.lines("Got UnsupportedOperationException");
+ }
+
+ @Override
+ protected boolean getTestWithDesugaring() {
+ return true;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
new file mode 100644
index 0000000..a5947eb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2022, 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.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceShortFieldTest extends VarHandleDesugaringTestBase {
+
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines("testGet", "0", "1", "2", "testCompareAndSet", "0", "1", "2", "3", "4");
+
+ private static final String MAIN_CLASS = VarHandle.InstanceShortField.typeName();
+ private static final String JAR_ENTRY = "varhandle/InstanceShortField.class";
+
+ @Override
+ protected String getMainClass() {
+ return MAIN_CLASS;
+ }
+
+ @Override
+ protected String getKeepRules() {
+ return "-keep class " + getMainClass() + "{ <fields>; }";
+ }
+
+ @Override
+ protected List<String> getJarEntries() {
+ return ImmutableList.of(JAR_ENTRY);
+ }
+
+ @Override
+ protected String getExpectedOutputForReferenceImplementation() {
+ return EXPECTED_OUTPUT;
+ }
+
+ @Override
+ protected String getExpectedOutputForDesugaringImplementation() {
+ return StringUtils.lines("Got UnsupportedOperationException");
+ }
+
+ @Override
+ protected boolean getTestWithDesugaring() {
+ return true;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
index 6a73d66..892cdc3 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
@@ -65,6 +65,10 @@
protected abstract String getExpectedOutputForReferenceImplementation();
+ protected String getExpectedOutputForDesugaringImplementation() {
+ return getExpectedOutputForReferenceImplementation();
+ }
+
protected String getExpectedOutputForArtImplementation() {
return getExpectedOutputForReferenceImplementation();
}
@@ -198,7 +202,7 @@
.getDexRuntimeVersion()
.isNewerThanOrEqual(Version.V13_0_0)
? getExpectedOutputForArtImplementation()
- : getExpectedOutputForReferenceImplementation()))
+ : getExpectedOutputForDesugaringImplementation()))
.inspect(this::inspect);
} else {
testForD8(parameters.getBackend())
@@ -220,6 +224,18 @@
// TODO(b/247076137: Also turn on VarHandle desugaring for R8 tests.
@Test
public void testR8() throws Throwable {
+ // TODO(b/247076137: The "default" VM is acting up on some tests - skip these as they will
+ // be fixed when VarHandle desugaring is enabled for R8.
+ if (parameters.isDexRuntime()
+ && parameters.asDexRuntime().getVersion().isEqualTo(Version.DEFAULT)
+ && parameters.getApiLevel().equals(AndroidApiLevel.B)
+ && (this instanceof VarHandleDesugaringInstanceBooleanFieldTest
+ || this instanceof VarHandleDesugaringInstanceByteFieldTest
+ || this instanceof VarHandleDesugaringInstanceShortFieldTest
+ || this instanceof VarHandleDesugaringInstanceFloatFieldTest
+ || this instanceof VarHandleDesugaringInstanceDoubleFieldTest)) {
+ return;
+ }
testForR8(parameters.getBackend())
.applyIf(
parameters.isDexRuntime(),
diff --git a/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java b/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
index 620e01b..0cb3d7f 100644
--- a/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
+++ b/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
@@ -29,6 +29,21 @@
public static final JavaExampleClassProxy InstanceLongField =
new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceLongField");
+ public static final JavaExampleClassProxy InstanceBooleanField =
+ new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceBooleanField");
+
+ public static final JavaExampleClassProxy InstanceByteField =
+ new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceByteField");
+
+ public static final JavaExampleClassProxy InstanceShortField =
+ new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceShortField");
+
+ public static final JavaExampleClassProxy InstanceFloatField =
+ new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceFloatField");
+
+ public static final JavaExampleClassProxy InstanceDoubleField =
+ new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceDoubleField");
+
public static final JavaExampleClassProxy InstanceObjectField =
new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceObjectField");
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
index 30b3240..5780485 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
@@ -79,6 +79,14 @@
this.recv = recv;
Field field = recv.getDeclaredField(name);
this.type = field.getType();
+ if (type.isPrimitive() && type != int.class && type != long.class) {
+ throw new UnsupportedOperationException(
+ "Using a VarHandle for a field of type '"
+ + type.getName()
+ + "' requires native VarHandle support available from Android 13. "
+ + "VarHandle desugaring only supports primitive types int and long and "
+ + "reference types.");
+ }
this.offset = U.objectFieldOffset(recv.getDeclaredField(name));
}