VarHandle desugar: Better handling of polymorphic return types
Bug: b/247076137
Change-Id: If14311abf0e2fe40a28f09dd0168a37d8523b6ba
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
index 380d5d4..b83c526 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.desugar.varhandle;
import com.android.tools.r8.cf.code.CfCheckCast;
+import com.android.tools.r8.cf.code.CfConstClass;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLoad;
@@ -404,16 +405,22 @@
}
assert newParameters.size() == proto.parameters.size();
DexString name = invoke.getMethod().getName();
- DexProto newProto =
- factory.createProto(
- factory.polymorphicMethods.varHandleCompareAndSetMethodNames.contains(name)
- ? proto.returnType
- : objectOrPrimitiveReturnType(proto.returnType),
- newParameters);
+ DexType returnType =
+ factory.polymorphicMethods.varHandleCompareAndSetMethodNames.contains(name)
+ ? proto.returnType
+ : objectOrPrimitiveReturnType(proto.returnType);
+ if (proto.returnType != returnType) {
+ if (proto.returnType.isPrimitiveType()) {
+ builder.add(new CfConstClass(factory.getBoxedForPrimitiveType(proto.returnType)));
+ } else {
+ builder.add(new CfConstClass(proto.returnType));
+ }
+ newParameters.add(factory.classType);
+ }
+ DexProto newProto = factory.createProto(returnType, newParameters);
DexMethod newMethod = factory.createMethod(factory.varHandleType, newProto, name);
builder.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, newMethod, false));
if (proto.returnType.isPrimitiveType() && !newProto.returnType.isPrimitiveType()) {
- assert proto.returnType.isPrimitiveType();
assert newProto.returnType == factory.objectType;
builder.add(new CfCheckCast(factory.getBoxedForPrimitiveType(proto.returnType)));
builder.add(
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 90c8eb5..9f1ba61 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
@@ -52,6 +52,8 @@
public static void registerSynthesizedCodeReferences(DexItemFactory factory) {
factory.createSynthesizedType("Ljava/lang/Byte;");
factory.createSynthesizedType("Ljava/lang/ClassCastException;");
+ factory.createSynthesizedType("Ljava/lang/Double;");
+ factory.createSynthesizedType("Ljava/lang/Float;");
factory.createSynthesizedType("Ljava/lang/Integer;");
factory.createSynthesizedType("Ljava/lang/Long;");
factory.createSynthesizedType("Ljava/lang/RuntimeException;");
@@ -179,6 +181,14 @@
builder.getType(),
factory.createProto(factory.longType, factory.objectType),
factory.createString("get"));
+ DexMethod getInBox =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.objectType,
+ factory.objectType,
+ factory.createType(factory.createString("Ljava/lang/Class;"))),
+ factory.createString("get"));
builder.setDirectMethods(
ImmutableList.of(
DexEncodedMethod.syntheticBuilder()
@@ -296,6 +306,14 @@
Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
.setCode(DesugarVarHandle_getLong(factory, getLong))
.disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
+ .setMethod(getInBox)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_getInBox(factory, getInBox))
+ .disableAndroidApiLevelCheck()
.build()));
}
@@ -1366,6 +1384,294 @@
ImmutableList.of());
}
+ public static CfCode DesugarVarHandle_getInBox(DexItemFactory factory, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ CfLabel label4 = new CfLabel();
+ CfLabel label5 = new CfLabel();
+ CfLabel label6 = new CfLabel();
+ CfLabel label7 = new CfLabel();
+ CfLabel label8 = new CfLabel();
+ CfLabel label9 = new CfLabel();
+ CfLabel label10 = new CfLabel();
+ CfLabel label11 = new CfLabel();
+ CfLabel label12 = new CfLabel();
+ CfLabel label13 = new CfLabel();
+ CfLabel label14 = new CfLabel();
+ CfLabel label15 = new CfLabel();
+ CfLabel label16 = new CfLabel();
+ CfLabel label17 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 4,
+ 5,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("type"))),
+ new CfStaticFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/Integer;"),
+ factory.classType,
+ factory.createString("TYPE"))),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label9),
+ label1,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createString("U"))),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("offset"))),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(factory.intType, factory.objectType, factory.longType),
+ factory.createString("getInt")),
+ false),
+ new CfStore(ValueType.INT, 3),
+ label2,
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstClass(factory.createType("Ljava/lang/Long;")),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+ label3,
+ new CfLoad(ValueType.INT, 3),
+ new CfNumberConversion(NumericType.INT, NumericType.LONG),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Long;"),
+ factory.createProto(factory.createType("Ljava/lang/Long;"), factory.longType),
+ factory.createString("valueOf")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label4,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.intType()
+ })),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstClass(factory.createType("Ljava/lang/Float;")),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label6),
+ label5,
+ new CfLoad(ValueType.INT, 3),
+ new CfNumberConversion(NumericType.INT, NumericType.FLOAT),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Float;"),
+ factory.createProto(factory.createType("Ljava/lang/Float;"), factory.floatType),
+ factory.createString("valueOf")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label6,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.intType()
+ })),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstClass(factory.createType("Ljava/lang/Double;")),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label8),
+ label7,
+ new CfLoad(ValueType.INT, 3),
+ new CfNumberConversion(NumericType.INT, NumericType.DOUBLE),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Double;"),
+ factory.createProto(
+ factory.createType("Ljava/lang/Double;"), factory.doubleType),
+ factory.createString("valueOf")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label8,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.intType()
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.createType("Ljava/lang/RuntimeException;")),
+ factory.createString("desugarWrongMethodTypeException")),
+ false),
+ new CfThrow(),
+ label9,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType)
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("type"))),
+ new CfStaticFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/Long;"),
+ factory.classType,
+ factory.createString("TYPE"))),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label16),
+ label10,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createString("U"))),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("offset"))),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(factory.longType, factory.objectType, factory.longType),
+ factory.createString("getLong")),
+ false),
+ new CfStore(ValueType.LONG, 3),
+ label11,
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstClass(factory.createType("Ljava/lang/Float;")),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label13),
+ label12,
+ new CfLoad(ValueType.LONG, 3),
+ new CfNumberConversion(NumericType.LONG, NumericType.FLOAT),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Float;"),
+ factory.createProto(factory.createType("Ljava/lang/Float;"), factory.floatType),
+ factory.createString("valueOf")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label13,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.longType(),
+ FrameType.longHighType()
+ })),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstClass(factory.createType("Ljava/lang/Double;")),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label15),
+ label14,
+ new CfLoad(ValueType.LONG, 3),
+ new CfNumberConversion(NumericType.LONG, NumericType.DOUBLE),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Double;"),
+ factory.createProto(
+ factory.createType("Ljava/lang/Double;"), factory.doubleType),
+ factory.createString("valueOf")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label15,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType),
+ FrameType.longType(),
+ FrameType.longHighType()
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.createType("Ljava/lang/RuntimeException;")),
+ factory.createString("desugarWrongMethodTypeException")),
+ false),
+ new CfThrow(),
+ label16,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.initializedNonNullReference(factory.classType)
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createString("U"))),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("offset"))),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(factory.objectType, factory.objectType, factory.longType),
+ factory.createString("getObject")),
+ false),
+ new CfReturn(ValueType.OBJECT),
+ label17),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
public static CfCode DesugarVarHandle_getInt(DexItemFactory factory, DexMethod method) {
CfLabel label0 = new CfLabel();
CfLabel label1 = new CfLabel();
@@ -1436,27 +1742,14 @@
new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
label3,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceFieldRead(
- factory.createField(
- factory.createType("Ljava/lang/invoke/VarHandle;"),
- factory.createType("Lsun/misc/Unsafe;"),
- factory.createString("U"))),
- new CfLoad(ValueType.OBJECT, 1),
- new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceFieldRead(
- factory.createField(
- factory.createType("Ljava/lang/invoke/VarHandle;"),
- factory.longType,
- factory.createString("offset"))),
new CfInvoke(
182,
factory.createMethod(
- factory.createType("Lsun/misc/Unsafe;"),
- factory.createProto(factory.longType, factory.objectType, factory.longType),
- factory.createString("getLong")),
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.createType("Ljava/lang/RuntimeException;")),
+ factory.createString("desugarWrongMethodTypeException")),
false),
- new CfNumberConversion(NumericType.LONG, NumericType.INT),
- new CfReturn(ValueType.INT),
+ new CfThrow(),
label4,
new CfFrame(
new Int2ObjectAVLTreeMap<>(
diff --git a/src/test/examplesJava9/varhandle/InstanceIntField.java b/src/test/examplesJava9/varhandle/InstanceIntField.java
index 0320030..aeadbcc 100644
--- a/src/test/examplesJava9/varhandle/InstanceIntField.java
+++ b/src/test/examplesJava9/varhandle/InstanceIntField.java
@@ -18,10 +18,54 @@
throw e;
}
- public static void testSet(VarHandle varHandle) {
+ public static void testGet(VarHandle varHandle) {
System.out.println("testGet");
InstanceIntField instance = new InstanceIntField();
+ varHandle.set(instance, 1);
+
+ System.out.println(varHandle.get(instance));
+ System.out.println((Object) varHandle.get(instance));
+ System.out.println((int) varHandle.get(instance));
+ System.out.println((long) varHandle.get(instance));
+ System.out.println((float) varHandle.get(instance));
+ System.out.println((double) varHandle.get(instance));
+ try {
+ System.out.println((boolean) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((byte) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((short) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((char) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((String) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ }
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testSet");
+
+ InstanceIntField instance = new InstanceIntField();
System.out.println((int) varHandle.get(instance));
// int and Integer values.
@@ -217,6 +261,7 @@
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
VarHandle varHandle =
MethodHandles.lookup().findVarHandle(InstanceIntField.class, "field", int.class);
+ testGet(varHandle);
testSet(varHandle);
testCompareAndSet(varHandle);
}
diff --git a/src/test/examplesJava9/varhandle/InstanceLongField.java b/src/test/examplesJava9/varhandle/InstanceLongField.java
index fac0ef3..b23e692 100644
--- a/src/test/examplesJava9/varhandle/InstanceLongField.java
+++ b/src/test/examplesJava9/varhandle/InstanceLongField.java
@@ -18,6 +18,55 @@
throw e;
}
+ public static void testGet(VarHandle varHandle) {
+ System.out.println("testGet");
+
+ InstanceLongField instance = new InstanceLongField();
+ varHandle.set(instance, 1L);
+
+ System.out.println(varHandle.get(instance));
+ System.out.println((Object) varHandle.get(instance));
+ System.out.println((long) varHandle.get(instance));
+ System.out.println((float) varHandle.get(instance));
+ System.out.println((double) varHandle.get(instance));
+ try {
+ System.out.println((boolean) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((byte) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((short) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((char) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((int) varHandle.get(instance));
+ System.out.println("Unexpected success 5");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ try {
+ System.out.println((String) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ }
+ }
+
public static void testSet(VarHandle varHandle) {
System.out.println("testSet");
@@ -187,6 +236,7 @@
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
VarHandle varHandle =
MethodHandles.lookup().findVarHandle(InstanceLongField.class, "field", long.class);
+ testGet(varHandle);
testSet(varHandle);
testCompareAndSet(varHandle);
}
diff --git a/src/test/examplesJava9/varhandle/InstanceStringField.java b/src/test/examplesJava9/varhandle/InstanceStringField.java
index 1be6f67..231ee6a 100644
--- a/src/test/examplesJava9/varhandle/InstanceStringField.java
+++ b/src/test/examplesJava9/varhandle/InstanceStringField.java
@@ -14,12 +14,31 @@
System.out.println(s);
}
- public static void testSet(VarHandle varHandle) {
+ public static void testGet(VarHandle varHandle) {
System.out.println("testGet");
InstanceStringField instance = new InstanceStringField();
// Then polymorphic invoke will remove the cast and make that as the return type of the get.
+ System.out.println((String) varHandle.get(instance));
+ varHandle.set(instance, "1");
+ System.out.println(varHandle.get(instance));
+ System.out.println((Object) varHandle.get(instance));
+ System.out.println((String) varHandle.get(instance));
+ System.out.println((CharSequence) varHandle.get(instance));
+ try {
+ System.out.println((Byte) varHandle.get(instance));
+ System.out.println("Unexpected success");
+ } catch (ClassCastException e) {
+ }
+ }
+
+ public static void testSet(VarHandle varHandle) {
+ System.out.println("testSet");
+
+ InstanceStringField instance = new InstanceStringField();
+
+ // Then polymorphic invoke will remove the cast and make that as the return type of the get.
println((String) varHandle.get(instance));
varHandle.set(instance, "1");
println((String) varHandle.get(instance));
@@ -39,6 +58,7 @@
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
VarHandle varHandle =
MethodHandles.lookup().findVarHandle(InstanceStringField.class, "field", Object.class);
+ testGet(varHandle);
testSet(varHandle);
testCompareAndSet(varHandle);
}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
index 7cfc0e5..f676891 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
@@ -17,6 +17,13 @@
private static final String EXPECTED_OUTPUT =
StringUtils.lines(
"testGet",
+ "1",
+ "1",
+ "1",
+ "1",
+ "1.0",
+ "1.0",
+ "testSet",
"0",
"1",
"2",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java
index 227cc76..7303ec5 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java
@@ -16,6 +16,12 @@
private static final String EXPECTED_OUTPUT =
StringUtils.lines(
+ "testGet",
+ "1",
+ "1",
+ "1",
+ "1.0",
+ "1.0",
"testSet",
"0",
"1",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceStringFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceStringFieldTest.java
index f33f52c..f1440c1 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceStringFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceStringFieldTest.java
@@ -15,7 +15,19 @@
public class VarHandleDesugaringInstanceStringFieldTest extends VarHandleDesugaringTestBase {
private static final String EXPECTED_OUTPUT =
- StringUtils.lines("testGet", "null", "1", "testCompareAndSet", "null", "1");
+ StringUtils.lines(
+ "testGet",
+ "null",
+ "1",
+ "1",
+ "1",
+ "1",
+ "testSet",
+ "null",
+ "1",
+ "testCompareAndSet",
+ "null",
+ "1");
private static final String MAIN_CLASS = VarHandle.InstanceStringField.typeName();
private static final String JAR_ENTRY = "varhandle/InstanceStringField.class";
@@ -38,4 +50,9 @@
protected String getExpectedOutputForReferenceImplementation() {
return EXPECTED_OUTPUT;
}
+
+ @Override
+ protected boolean getTestWithDesugaring() {
+ return true;
+ }
}
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 5780485..2ba4cf4 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
@@ -142,11 +142,38 @@
return U.getObject(ct1, offset);
}
+ Object getInBox(Object ct1, Class<?> expectedBox) {
+ if (type == int.class) {
+ int value = U.getInt(ct1, offset);
+ if (expectedBox == Long.class) {
+ return Long.valueOf(value);
+ }
+ if (expectedBox == Float.class) {
+ return Float.valueOf(value);
+ }
+ if (expectedBox == Double.class) {
+ return Double.valueOf(value);
+ }
+ throw desugarWrongMethodTypeException();
+ }
+ if (type == long.class) {
+ long value = U.getLong(ct1, offset);
+ if (expectedBox == Float.class) {
+ return Float.valueOf(value);
+ }
+ if (expectedBox == Double.class) {
+ return Double.valueOf(value);
+ }
+ throw desugarWrongMethodTypeException();
+ }
+ return U.getObject(ct1, offset);
+ }
+
int getInt(Object ct1) {
if (type == int.class) {
return U.getInt(ct1, offset);
} else if (type == long.class) {
- return (int) U.getLong(ct1, offset);
+ throw desugarWrongMethodTypeException();
} else {
return toIntIfPossible(U.getObject(ct1, offset), true);
}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java
index 369bc51..7052773 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java
@@ -223,7 +223,8 @@
for (String prefix : ImmutableList.of("get", "set", "compareAndSet")) {
if (name.startsWith(prefix)
&& (name.substring(prefix.length()).equals("Int")
- || name.substring(prefix.length()).equals("Long"))) {
+ || name.substring(prefix.length()).equals("Long")
+ || name.substring(prefix.length()).equals("InBox"))) {
return prefix;
}
}