VarHandle desugar: Add support for setRelease
Bug: b/247076137
Change-Id: I9805c4aeae8081039c84fe62f7c89f17a5840292
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 574de7c..4df3ab0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -365,6 +365,7 @@
public final DexString weakCompareAndSetString = createString("weakCompareAndSet");
public final DexString getVolatileString = createString("getVolatile");
public final DexString setVolatileString = createString("setVolatile");
+ public final DexString setReleaseString = createString("setRelease");
// Method names used on MethodHandles.
public final DexString lookupString = createString("lookup");
@@ -2292,7 +2293,7 @@
"getVolatile");
private final Set<DexString> varHandleSetMethods =
- createStrings(setString, "setOpaque", "setRelease", "setVolatile");
+ createStrings(setString, "setOpaque", setReleaseString, setVolatileString);
public final Set<DexString> varHandleCompareAndSetMethodNames =
createStrings(
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 1cf4e64..d8382b7 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
@@ -294,7 +294,9 @@
} else if (name.equals(factory.getString) || name.equals(factory.getVolatileString)) {
assert arity == 1 || arity == 2;
return computeDesugarSignaturePolymorphicMethod(invoke, arity);
- } else if (name.equals(factory.setString) || name.equals(factory.setVolatileString)) {
+ } else if (name.equals(factory.setString)
+ || name.equals(factory.setVolatileString)
+ || name.equals(factory.setReleaseString)) {
assert arity == 2 || arity == 3;
return computeDesugarSignaturePolymorphicMethod(invoke, arity - 1);
} else {
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 63741f0..f5dc15e 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
@@ -113,23 +113,6 @@
.setAccessFlags(FieldAccessFlags.createPublicFinalSynthetic())
.disableAndroidApiLevelCheck()
.build()));
- DexMethod getVolatileArrayLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.longType, factory.createType(factory.createString("[J")), factory.intType),
- factory.createString("getVolatile"));
- DexMethod getVolatileArrayInt =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.intType, factory.createType(factory.createString("[I")), factory.intType),
- factory.createString("getVolatile"));
- DexMethod toIntIfPossible =
- factory.createMethod(
- builder.getType(),
- factory.createProto(factory.intType, factory.objectType, factory.booleanType),
- factory.createString("toIntIfPossible"));
DexMethod compareAndSet =
factory.createMethod(
builder.getType(),
@@ -145,29 +128,6 @@
factory.intType,
factory.createType(factory.createString("Ljava/lang/Class;"))),
factory.createString("get"));
- DexMethod setVolatileArrayInt =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.voidType,
- factory.createType(factory.createString("[I")),
- factory.intType,
- factory.intType),
- factory.createString("setVolatile"));
- DexMethod setArrayInt =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.voidType,
- factory.createType(factory.createString("[I")),
- factory.intType,
- factory.intType),
- factory.createString("set"));
- DexMethod setLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(factory.voidType, factory.objectType, factory.longType),
- factory.createString("set"));
DexMethod boxIntIfPossible =
factory.createMethod(
builder.getType(),
@@ -212,27 +172,6 @@
builder.getType(),
factory.createProto(factory.longType, factory.objectType),
factory.createString("get"));
- DexMethod getArrayLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.longType, factory.createType(factory.createString("[J")), factory.intType),
- factory.createString("get"));
- DexMethod getVolatileInt =
- factory.createMethod(
- builder.getType(),
- factory.createProto(factory.intType, factory.objectType),
- factory.createString("getVolatile"));
- DexMethod compareAndSetArrayLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.booleanType,
- factory.createType(factory.createString("[J")),
- factory.intType,
- factory.longType,
- factory.longType),
- factory.createString("compareAndSet"));
DexMethod setVolatileInt =
factory.createMethod(
builder.getType(),
@@ -243,19 +182,6 @@
builder.getType(),
factory.createProto(factory.longType, factory.objectType),
factory.createString("getVolatile"));
- DexMethod getInBox =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.objectType,
- factory.objectType,
- factory.createType(factory.createString("Ljava/lang/Class;"))),
- factory.createString("get"));
- DexMethod getVolatileArray =
- factory.createMethod(
- builder.getType(),
- factory.createProto(factory.objectType, factory.objectType, factory.intType),
- factory.createString("getVolatile"));
DexMethod get =
factory.createMethod(
builder.getType(),
@@ -269,15 +195,6 @@
factory.objectType,
factory.createType(factory.createString("Ljava/lang/Class;"))),
factory.createString("getVolatile"));
- DexMethod setVolatileArrayLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.voidType,
- factory.createType(factory.createString("[J")),
- factory.intType,
- factory.longType),
- factory.createString("setVolatile"));
DexMethod compareAndSetArrayInt =
factory.createMethod(
builder.getType(),
@@ -299,46 +216,11 @@
factory.createProto(
factory.booleanType, factory.objectType, factory.objectType, factory.objectType),
factory.createString("weakCompareAndSet"));
- DexMethod constructor_1 =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.voidType, factory.createType(factory.createString("Ljava/lang/Class;"))),
- factory.createString("<init>"));
- DexMethod constructor_3 =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.voidType,
- factory.createType(factory.createString("Ljava/lang/Class;")),
- factory.createType(factory.createString("Ljava/lang/String;")),
- factory.createType(factory.createString("Ljava/lang/Class;"))),
- factory.createString("<init>"));
- DexMethod getVolatile =
- factory.createMethod(
- builder.getType(),
- factory.createProto(factory.objectType, factory.objectType),
- factory.createString("getVolatile"));
DexMethod arrayRequiringNativeSupport =
factory.createMethod(
builder.getType(),
factory.createProto(factory.createType(factory.createString("Ljava/lang/String;"))),
factory.createString("arrayRequiringNativeSupport"));
- DexMethod weakCompareAndSetArrayLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.booleanType,
- factory.createType(factory.createString("[J")),
- factory.intType,
- factory.longType,
- factory.longType),
- factory.createString("weakCompareAndSet"));
- DexMethod setVolatile =
- factory.createMethod(
- builder.getType(),
- factory.createProto(factory.voidType, factory.objectType, factory.objectType),
- factory.createString("setVolatile"));
DexMethod boxLongIfPossible =
factory.createMethod(
builder.getType(),
@@ -347,27 +229,11 @@
factory.longType,
factory.createType(factory.createString("Ljava/lang/Class;"))),
factory.createString("boxLongIfPossible"));
- DexMethod weakCompareAndSetArrayInt =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.booleanType,
- factory.createType(factory.createString("[I")),
- factory.intType,
- factory.intType,
- factory.intType),
- factory.createString("weakCompareAndSet"));
DexMethod toLongIfPossible =
factory.createMethod(
builder.getType(),
factory.createProto(factory.longType, factory.objectType, factory.booleanType),
factory.createString("toLongIfPossible"));
- DexMethod compareAndSetLong =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.booleanType, factory.objectType, factory.longType, factory.longType),
- factory.createString("compareAndSet"));
DexMethod set =
factory.createMethod(
builder.getType(),
@@ -389,12 +255,6 @@
factory.objectType,
factory.objectType),
factory.createString("weakCompareAndSet"));
- DexMethod weakCompareAndSetInt =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.booleanType, factory.objectType, factory.intType, factory.intType),
- factory.createString("weakCompareAndSet"));
DexMethod setArray =
factory.createMethod(
builder.getType(),
@@ -413,6 +273,194 @@
factory.createProto(
factory.booleanType, factory.objectType, factory.longType, factory.longType),
factory.createString("weakCompareAndSet"));
+ DexMethod getVolatileArrayInBox =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.objectType,
+ factory.objectType,
+ factory.intType,
+ factory.createType(factory.createString("Ljava/lang/Class;"))),
+ factory.createString("getVolatile"));
+ DexMethod getVolatileArrayLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.longType, factory.createType(factory.createString("[J")), factory.intType),
+ factory.createString("getVolatile"));
+ DexMethod getVolatileArrayInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.intType, factory.createType(factory.createString("[I")), factory.intType),
+ factory.createString("getVolatile"));
+ DexMethod toIntIfPossible =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.intType, factory.objectType, factory.booleanType),
+ factory.createString("toIntIfPossible"));
+ DexMethod setReleaseLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.voidType, factory.objectType, factory.longType),
+ factory.createString("setRelease"));
+ DexMethod setVolatileArrayInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType,
+ factory.createType(factory.createString("[I")),
+ factory.intType,
+ factory.intType),
+ factory.createString("setVolatile"));
+ DexMethod setArrayInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType,
+ factory.createType(factory.createString("[I")),
+ factory.intType,
+ factory.intType),
+ factory.createString("set"));
+ DexMethod setLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.voidType, factory.objectType, factory.longType),
+ factory.createString("set"));
+ DexMethod getArrayLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.longType, factory.createType(factory.createString("[J")), factory.intType),
+ factory.createString("get"));
+ DexMethod getVolatileInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.intType, factory.objectType),
+ factory.createString("getVolatile"));
+ DexMethod compareAndSetArrayLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.booleanType,
+ factory.createType(factory.createString("[J")),
+ factory.intType,
+ factory.longType,
+ factory.longType),
+ factory.createString("compareAndSet"));
+ DexMethod getInBox =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.objectType,
+ factory.objectType,
+ factory.createType(factory.createString("Ljava/lang/Class;"))),
+ factory.createString("get"));
+ DexMethod setReleaseInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.voidType, factory.objectType, factory.intType),
+ factory.createString("setRelease"));
+ DexMethod getVolatileArray =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.objectType, factory.objectType, factory.intType),
+ factory.createString("getVolatile"));
+ DexMethod setReleaseArray =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.intType, factory.objectType),
+ factory.createString("setRelease"));
+ DexMethod setRelease =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.voidType, factory.objectType, factory.objectType),
+ factory.createString("setRelease"));
+ DexMethod setReleaseArrayLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType,
+ factory.createType(factory.createString("[J")),
+ factory.intType,
+ factory.longType),
+ factory.createString("setRelease"));
+ DexMethod setVolatileArrayLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType,
+ factory.createType(factory.createString("[J")),
+ factory.intType,
+ factory.longType),
+ factory.createString("setVolatile"));
+ DexMethod setReleaseArrayInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType,
+ factory.createType(factory.createString("[I")),
+ factory.intType,
+ factory.intType),
+ factory.createString("setRelease"));
+ DexMethod constructor_1 =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType, factory.createType(factory.createString("Ljava/lang/Class;"))),
+ factory.createString("<init>"));
+ DexMethod constructor_3 =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.voidType,
+ factory.createType(factory.createString("Ljava/lang/Class;")),
+ factory.createType(factory.createString("Ljava/lang/String;")),
+ factory.createType(factory.createString("Ljava/lang/Class;"))),
+ factory.createString("<init>"));
+ DexMethod getVolatile =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.objectType, factory.objectType),
+ factory.createString("getVolatile"));
+ DexMethod weakCompareAndSetArrayLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.booleanType,
+ factory.createType(factory.createString("[J")),
+ factory.intType,
+ factory.longType,
+ factory.longType),
+ factory.createString("weakCompareAndSet"));
+ DexMethod setVolatile =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(factory.voidType, factory.objectType, factory.objectType),
+ factory.createString("setVolatile"));
+ DexMethod weakCompareAndSetArrayInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.booleanType,
+ factory.createType(factory.createString("[I")),
+ factory.intType,
+ factory.intType,
+ factory.intType),
+ factory.createString("weakCompareAndSet"));
+ DexMethod compareAndSetLong =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.booleanType, factory.objectType, factory.longType, factory.longType),
+ factory.createString("compareAndSet"));
+ DexMethod weakCompareAndSetInt =
+ factory.createMethod(
+ builder.getType(),
+ factory.createProto(
+ factory.booleanType, factory.objectType, factory.intType, factory.intType),
+ factory.createString("weakCompareAndSet"));
DexMethod compareAndSetArray =
factory.createMethod(
builder.getType(),
@@ -423,15 +471,6 @@
factory.objectType,
factory.objectType),
factory.createString("compareAndSet"));
- DexMethod getVolatileArrayInBox =
- factory.createMethod(
- builder.getType(),
- factory.createProto(
- factory.objectType,
- factory.objectType,
- factory.intType,
- factory.createType(factory.createString("Ljava/lang/Class;"))),
- factory.createString("getVolatile"));
DexMethod getArray =
factory.createMethod(
builder.getType(),
@@ -694,6 +733,14 @@
.disableAndroidApiLevelCheck()
.build(),
DexEncodedMethod.syntheticBuilder()
+ .setMethod(setReleaseLong)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_setReleaseLong(factory, setReleaseLong))
+ .disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
.setMethod(setVolatileArrayInt)
.setAccessFlags(
MethodAccessFlags.fromSharedAccessFlags(
@@ -750,6 +797,14 @@
.disableAndroidApiLevelCheck()
.build(),
DexEncodedMethod.syntheticBuilder()
+ .setMethod(setReleaseInt)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_setReleaseInt(factory, setReleaseInt))
+ .disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
.setMethod(getVolatileArray)
.setAccessFlags(
MethodAccessFlags.fromSharedAccessFlags(
@@ -758,6 +813,30 @@
.disableAndroidApiLevelCheck()
.build(),
DexEncodedMethod.syntheticBuilder()
+ .setMethod(setReleaseArray)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_setReleaseArray(factory, setReleaseArray))
+ .disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
+ .setMethod(setRelease)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_setRelease(factory, setRelease))
+ .disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
+ .setMethod(setReleaseArrayLong)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_setReleaseArrayLong(factory, setReleaseArrayLong))
+ .disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
.setMethod(setVolatileArrayLong)
.setAccessFlags(
MethodAccessFlags.fromSharedAccessFlags(
@@ -766,6 +845,14 @@
.disableAndroidApiLevelCheck()
.build(),
DexEncodedMethod.syntheticBuilder()
+ .setMethod(setReleaseArrayInt)
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+ .setCode(DesugarVarHandle_setReleaseArrayInt(factory, setReleaseArrayInt))
+ .disableAndroidApiLevelCheck()
+ .build(),
+ DexEncodedMethod.syntheticBuilder()
.setMethod(getVolatile)
.setAccessFlags(
MethodAccessFlags.fromSharedAccessFlags(
@@ -6009,6 +6096,827 @@
ImmutableList.of());
}
+ public static CfCode DesugarVarHandle_setRelease(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();
+ return new CfCode(
+ method.holder,
+ 5,
+ 3,
+ 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, label2),
+ label1,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstNumber(0, ValueType.INT),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.intType, factory.objectType, factory.booleanType),
+ factory.createString("toIntIfPossible")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.voidType, factory.objectType, factory.intType),
+ factory.createString("setRelease")),
+ false),
+ new CfGoto(label5),
+ label2,
+ 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.objectType)
+ })),
+ 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, label4),
+ label3,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfConstNumber(0, ValueType.INT),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.longType, factory.objectType, factory.booleanType),
+ factory.createString("toLongIfPossible")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.voidType, factory.objectType, factory.longType),
+ factory.createString("setRelease")),
+ false),
+ new CfGoto(label5),
+ label4,
+ 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.objectType)
+ })),
+ 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 CfLoad(ValueType.OBJECT, 2),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.objectType),
+ factory.createString("putOrderedObject")),
+ false),
+ label5,
+ 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.objectType)
+ })),
+ new CfReturnVoid(),
+ label6),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode DesugarVarHandle_setReleaseArray(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();
+ return new CfCode(
+ method.holder,
+ 7,
+ 6,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("recv"))),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.classType,
+ factory.createProto(factory.booleanType),
+ factory.createString("isArray")),
+ false),
+ new CfIf(If.Type.EQ, ValueType.INT, label1),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("recv"))),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.objectType,
+ factory.createProto(factory.classType),
+ factory.createString("getClass")),
+ false),
+ new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+ label1,
+ 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.intType(),
+ FrameType.initializedNonNullReference(factory.objectType)
+ })),
+ new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfInvoke(
+ 183,
+ factory.createMethod(
+ factory.createType("Ljava/lang/UnsupportedOperationException;"),
+ factory.createProto(factory.voidType),
+ factory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label2,
+ 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.intType(),
+ FrameType.initializedNonNullReference(factory.objectType)
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("offset"))),
+ new CfLoad(ValueType.INT, 2),
+ new CfNumberConversion(NumericType.INT, NumericType.LONG),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("arrayIndexScale"))),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+ new CfStore(ValueType.LONG, 4),
+ label3,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("recv"))),
+ new CfConstClass(factory.intArrayType),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label5),
+ label4,
+ 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.LONG, 4),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfConstNumber(0, ValueType.INT),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.intType, factory.objectType, factory.booleanType),
+ factory.createString("toIntIfPossible")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.intType),
+ factory.createString("putOrderedInt")),
+ false),
+ new CfGoto(label8),
+ label5,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.intType(),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.longType(),
+ FrameType.longHighType()
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("recv"))),
+ new CfConstClass(factory.longArrayType),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label7),
+ label6,
+ 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.LONG, 4),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfConstNumber(0, ValueType.INT),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.longType, factory.objectType, factory.booleanType),
+ factory.createString("toLongIfPossible")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.longType),
+ factory.createString("putOrderedLong")),
+ false),
+ new CfGoto(label8),
+ label7,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.intType(),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.longType(),
+ FrameType.longHighType()
+ })),
+ 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.LONG, 4),
+ new CfLoad(ValueType.OBJECT, 3),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.objectType),
+ factory.createString("putOrderedObject")),
+ false),
+ label8,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.intType(),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.longType(),
+ FrameType.longHighType()
+ })),
+ new CfReturnVoid(),
+ label9),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode DesugarVarHandle_setReleaseArrayInt(
+ 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();
+ return new CfCode(
+ method.holder,
+ 6,
+ 6,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("recv"))),
+ new CfConstClass(factory.intArrayType),
+ new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+ label1,
+ new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfInvoke(
+ 183,
+ factory.createMethod(
+ factory.createType("Ljava/lang/UnsupportedOperationException;"),
+ factory.createProto(factory.voidType),
+ factory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label2,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.intArrayType),
+ FrameType.intType(),
+ FrameType.intType()
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("offset"))),
+ new CfLoad(ValueType.INT, 2),
+ new CfNumberConversion(NumericType.INT, NumericType.LONG),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("arrayIndexScale"))),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+ new CfStore(ValueType.LONG, 4),
+ 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.LONG, 4),
+ new CfLoad(ValueType.INT, 3),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.intType),
+ factory.createString("putOrderedInt")),
+ false),
+ label4,
+ new CfReturnVoid(),
+ label5),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode DesugarVarHandle_setReleaseArrayLong(
+ 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();
+ return new CfCode(
+ method.holder,
+ 6,
+ 7,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.classType,
+ factory.createString("recv"))),
+ new CfConstClass(factory.longArrayType),
+ new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+ label1,
+ new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfInvoke(
+ 183,
+ factory.createMethod(
+ factory.createType("Ljava/lang/UnsupportedOperationException;"),
+ factory.createProto(factory.voidType),
+ factory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label2,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.longArrayType),
+ FrameType.intType(),
+ FrameType.longType(),
+ FrameType.longHighType()
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("offset"))),
+ new CfLoad(ValueType.INT, 2),
+ new CfNumberConversion(NumericType.INT, NumericType.LONG),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInstanceFieldRead(
+ factory.createField(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.longType,
+ factory.createString("arrayIndexScale"))),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+ new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+ new CfStore(ValueType.LONG, 5),
+ 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.LONG, 5),
+ new CfLoad(ValueType.LONG, 3),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.longType),
+ factory.createString("putOrderedLong")),
+ false),
+ label4,
+ new CfReturnVoid(),
+ label5),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode DesugarVarHandle_setReleaseInt(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();
+ return new CfCode(
+ method.holder,
+ 6,
+ 3,
+ 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, label2),
+ 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 CfLoad(ValueType.INT, 2),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.intType),
+ factory.createString("putOrderedInt")),
+ false),
+ new CfGoto(label5),
+ label2,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.intType()
+ })),
+ 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, 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 CfLoad(ValueType.INT, 2),
+ new CfNumberConversion(NumericType.INT, NumericType.LONG),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.longType),
+ factory.createString("putOrderedLong")),
+ false),
+ new CfGoto(label5),
+ label4,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.intType()
+ })),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfLoad(ValueType.INT, 2),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Integer;"),
+ factory.createProto(factory.createType("Ljava/lang/Integer;"), factory.intType),
+ factory.createString("valueOf")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Ljava/lang/invoke/VarHandle;"),
+ factory.createProto(factory.voidType, factory.objectType, factory.objectType),
+ factory.createString("setRelease")),
+ false),
+ label5,
+ new CfFrame(
+ new Int2ObjectAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initializedNonNullReference(
+ factory.createType("Ljava/lang/invoke/VarHandle;")),
+ FrameType.initializedNonNullReference(factory.objectType),
+ FrameType.intType()
+ })),
+ new CfReturnVoid(),
+ label6),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode DesugarVarHandle_setReleaseLong(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();
+ return new CfCode(
+ method.holder,
+ 6,
+ 4,
+ 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/Long;"),
+ factory.classType,
+ factory.createString("TYPE"))),
+ new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+ 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 CfLoad(ValueType.LONG, 2),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.longType),
+ factory.createString("putOrderedLong")),
+ false),
+ new CfGoto(label5),
+ label2,
+ 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.longType(),
+ FrameType.longHighType()
+ })),
+ 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, label4),
+ label3,
+ 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(),
+ 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.longType(),
+ FrameType.longHighType()
+ })),
+ 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 CfLoad(ValueType.LONG, 2),
+ new CfInvoke(
+ 184,
+ factory.createMethod(
+ factory.createType("Ljava/lang/Long;"),
+ factory.createProto(factory.createType("Ljava/lang/Long;"), factory.longType),
+ factory.createString("valueOf")),
+ false),
+ new CfInvoke(
+ 182,
+ factory.createMethod(
+ factory.createType("Lsun/misc/Unsafe;"),
+ factory.createProto(
+ factory.voidType, factory.objectType, factory.longType, factory.objectType),
+ factory.createString("putOrderedObject")),
+ false),
+ label5,
+ 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.longType(),
+ FrameType.longHighType()
+ })),
+ new CfReturnVoid(),
+ label6),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
public static CfCode DesugarVarHandle_setVolatile(DexItemFactory factory, DexMethod method) {
CfLabel label0 = new CfLabel();
CfLabel label1 = new CfLabel();
diff --git a/src/test/examplesJava9/varhandle/ArrayOfInt.java b/src/test/examplesJava9/varhandle/ArrayOfInt.java
index 0689387..dd4445f 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfInt.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfInt.java
@@ -456,6 +456,144 @@
}
}
+ public static void testSetRelease() {
+ System.out.println("testSetRelease");
+
+ VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);
+ int[] array = new int[2];
+
+ // int and Integer values.
+ arrayVarHandle.setRelease(array, 0, 1);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, 2);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Integer.valueOf(3));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Integer.valueOf(4));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+
+ // int and Integer compatible values.
+ arrayVarHandle.setRelease(array, 0, (byte) 5);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, (byte) 6);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Byte.valueOf((byte) 7));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Byte.valueOf((byte) 8));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, '0');
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, '1');
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Character.valueOf('2'));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Character.valueOf('3'));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, (short) 9);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, (short) 10);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Short.valueOf((short) 11));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Short.valueOf((short) 12));
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+
+ // int and Integer non-compatible values.
+ try {
+ arrayVarHandle.setRelease(array, 0, true);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, 13L);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, Long.valueOf(13L));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, 1.3f);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, Float.valueOf(1.3f));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, 1.4);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, Double.valueOf(1.4));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, new Object());
+ System.out.println("Unexpected success");
+ } catch (ClassCastException e) {
+ // The reference implementation throws ClassCastException.
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ } catch (RuntimeException e) {
+ // The Art and desugaring throws WrongMethodTypeException.
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, "X");
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((int) arrayVarHandle.get(array, 0));
+ System.out.println((int) arrayVarHandle.get(array, 1));
+ }
+ }
+
public static void testCompareAndSet() {
System.out.println("testCompareAndSet");
@@ -522,6 +660,7 @@
testGetVolatile();
testSet();
testSetVolatile();
+ testSetRelease();
testCompareAndSet();
testWeakCompareAndSet();
testArrayVarHandleForNonSingleDimension();
diff --git a/src/test/examplesJava9/varhandle/ArrayOfLong.java b/src/test/examplesJava9/varhandle/ArrayOfLong.java
index a7f7ba3..e66a441 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfLong.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfLong.java
@@ -468,6 +468,140 @@
}
}
+ public static void testSetRelease() {
+ System.out.println("testSetRelease");
+
+ VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(long[].class);
+ long[] array = new long[2];
+
+ // long and Long values.
+ arrayVarHandle.setRelease(array, 0, 1L);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, 2L);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Long.valueOf(3L));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Long.valueOf(4L));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+
+ // long and Long compatible values.
+ arrayVarHandle.setRelease(array, 0, (byte) 5);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, (byte) 6);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Byte.valueOf((byte) 7));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Byte.valueOf((byte) 8));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, '0');
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, '1');
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Character.valueOf('2'));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Character.valueOf('3'));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, (short) 9);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, (short) 10);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Short.valueOf((short) 11));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Short.valueOf((short) 12));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, 13);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, 14);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 0, Integer.valueOf(15));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ arrayVarHandle.setRelease(array, 1, Integer.valueOf(16));
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+
+ // long and Long non-compatible values.
+ try {
+ arrayVarHandle.setRelease(array, 0, true);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, 1.3f);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, Float.valueOf(1.3f));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, 1.4);
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, Double.valueOf(1.4));
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, new Object());
+ System.out.println("Unexpected success");
+ } catch (ClassCastException e) {
+ // The reference implementation throws ClassCastException.
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ } catch (RuntimeException e) {
+ // The Art and desugaring throws WrongMethodTypeException.
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ try {
+ arrayVarHandle.setRelease(array, 0, "X");
+ System.out.println("Unexpected success");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println((long) arrayVarHandle.get(array, 0));
+ System.out.println((long) arrayVarHandle.get(array, 1));
+ }
+ }
+
public static void testCompareAndSet() {
System.out.println("testCompareAndSet");
@@ -534,6 +668,7 @@
testGetVolatile();
testSet();
testSetVolatile();
+ testSetRelease();
testCompareAndSet();
testWeakCompareAndSet();
testArrayVarHandleForNonSingleDimension();
diff --git a/src/test/examplesJava9/varhandle/ArrayOfObject.java b/src/test/examplesJava9/varhandle/ArrayOfObject.java
index 07f7708..f7189d8 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfObject.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfObject.java
@@ -501,6 +501,105 @@
}
}
+ public static void testSetRelease() {
+ System.out.println("testSetRelease");
+
+ VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(Object[].class);
+ Object[] array = new Object[2];
+
+ Object o;
+ {
+ int index = 0;
+ byte b;
+ arrayVarHandle.setRelease(array, index, (byte) 5);
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((byte) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Byte);
+ b = (byte) arrayVarHandle.get(array, index);
+ System.out.println(b == (byte) 5);
+ arrayVarHandle.setRelease(array, index, Byte.valueOf((byte) 6));
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((byte) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Byte);
+ b = (byte) arrayVarHandle.get(array, index);
+ System.out.println(b == 6);
+ }
+ {
+ int index = 0;
+ short s;
+ arrayVarHandle.setRelease(array, index, (short) 7);
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((short) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Short);
+ s = (short) arrayVarHandle.get(array, index);
+ System.out.println(s == (short) 7);
+ arrayVarHandle.setRelease(array, index, Short.valueOf((short) 8));
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((short) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Short);
+ s = (short) arrayVarHandle.get(array, index);
+ System.out.println(s == 8);
+ }
+ {
+ int index = 0;
+ float f;
+ arrayVarHandle.setRelease(array, index, (float) 9.0f);
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((float) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Float);
+ f = (float) arrayVarHandle.get(array, index);
+ System.out.println(f == (float) 9.0f);
+ arrayVarHandle.setRelease(array, index, Float.valueOf(10.0f));
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((float) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Float);
+ f = (float) arrayVarHandle.get(array, index);
+ System.out.println(f == 10.0f);
+ }
+ {
+ int index = 0;
+ double d;
+ arrayVarHandle.setRelease(array, index, (double) 11.0);
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((double) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Double);
+ d = (double) arrayVarHandle.get(array, index);
+ System.out.println(d == (double) 11.0);
+ arrayVarHandle.setRelease(array, index, Double.valueOf(12.0));
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((double) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Double);
+ d = (double) arrayVarHandle.get(array, index);
+ System.out.println(d == 12.0);
+ }
+ {
+ int index = 0;
+ char c;
+ arrayVarHandle.setRelease(array, index, 'A');
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((char) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Character);
+ c = (char) arrayVarHandle.get(array, index);
+ System.out.println(c == 'A');
+ arrayVarHandle.setRelease(array, index, Character.valueOf('B'));
+ System.out.println(arrayVarHandle.get(array, index));
+ System.out.println((char) arrayVarHandle.get(array, index));
+ o = arrayVarHandle.get(array, index);
+ System.out.println(o instanceof Character);
+ c = (char) arrayVarHandle.get(array, index);
+ System.out.println(c == 'B');
+ }
+ }
+
public static void testCompareAndSet() {
System.out.println("testCompareAndSet");
@@ -691,6 +790,7 @@
testGetVolatile();
testSet();
testSetVolatile();
+ testSetRelease();
testCompareAndSet();
testWeakCompareAndSet();
testArrayVarHandleForNonSingleDimension();
diff --git a/src/test/examplesJava9/varhandle/InstanceIntField.java b/src/test/examplesJava9/varhandle/InstanceIntField.java
index 9462fdd..6970f2e 100644
--- a/src/test/examplesJava9/varhandle/InstanceIntField.java
+++ b/src/test/examplesJava9/varhandle/InstanceIntField.java
@@ -236,6 +236,71 @@
}
}
+ public static void testSetRelease(VarHandle varHandle) {
+ System.out.println("testSetRelease");
+
+ InstanceIntField instance = new InstanceIntField();
+ System.out.println((int) varHandle.get(instance));
+
+ // int and Integer values.
+ varHandle.setRelease(instance, (int) 1);
+ System.out.println((int) varHandle.get(instance));
+ varHandle.setRelease(instance, Integer.valueOf(2));
+ System.out.println(varHandle.get(instance));
+
+ // int and Integer compatible values.
+ varHandle.setRelease(instance, (byte) 3);
+ System.out.println((int) varHandle.get(instance));
+ varHandle.setRelease(instance, Byte.valueOf((byte) 4));
+ System.out.println((int) varHandle.get(instance));
+ varHandle.setRelease(instance, '0');
+ System.out.println((int) varHandle.get(instance));
+ varHandle.setRelease(instance, Character.valueOf('1'));
+ System.out.println((int) varHandle.get(instance));
+ varHandle.setRelease(instance, (short) 5);
+ System.out.println((int) varHandle.get(instance));
+ varHandle.setRelease(instance, Short.valueOf((short) 6));
+ System.out.println((int) varHandle.get(instance));
+
+ // int and Integer non-compatible values.
+ try {
+ varHandle.setRelease(instance, true);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, 3L);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, Long.valueOf(3));
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, "3");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, 3.0f);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, 3.0);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ }
+
public static void testCompareAndSet(VarHandle varHandle) {
System.out.println("testCompareAndSet");
@@ -508,6 +573,7 @@
testGetVolatile(varHandle);
testSet(varHandle);
testSetVolatile(varHandle);
+ testSetRelease(varHandle);
testCompareAndSet(varHandle);
testWeakCompareAndSet(varHandle);
}
diff --git a/src/test/examplesJava9/varhandle/InstanceLongField.java b/src/test/examplesJava9/varhandle/InstanceLongField.java
index 639b6fd..7ecc8a7 100644
--- a/src/test/examplesJava9/varhandle/InstanceLongField.java
+++ b/src/test/examplesJava9/varhandle/InstanceLongField.java
@@ -230,6 +230,63 @@
}
}
+ public static void testSetRelease(VarHandle varHandle) {
+ System.out.println("testSetRelease");
+
+ InstanceLongField instance = new InstanceLongField();
+ System.out.println((long) varHandle.get(instance));
+
+ // Long value.
+ varHandle.setRelease(instance, (long) 1);
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, Long.valueOf(2));
+ System.out.println(varHandle.get(instance));
+
+ // Long compatible values.
+ varHandle.setRelease(instance, (byte) 3);
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, Byte.valueOf((byte) 4));
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, '0');
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, Character.valueOf('1'));
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, (short) 5);
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, Short.valueOf((short) 6));
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, (int) 7);
+ System.out.println((long) varHandle.get(instance));
+ varHandle.setRelease(instance, Integer.valueOf(8));
+ System.out.println((long) varHandle.get(instance));
+
+ // Long non-compatible values.
+ try {
+ varHandle.setRelease(instance, true);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, "3");
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, 3.0f);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ try {
+ varHandle.setRelease(instance, 3.0);
+ } catch (RuntimeException e) {
+ checkJavaLangInvokeWrongMethodTypeException(e);
+ System.out.println(varHandle.get(instance));
+ }
+ }
+
public static void testCompareAndSet(VarHandle varHandle) {
System.out.println("testCompareAndSet");
@@ -458,6 +515,7 @@
testGetVolatile(varHandle);
testSet(varHandle);
testSetVolatile(varHandle);
+ testSetRelease(varHandle);
testCompareAndSet(varHandle);
testWeakCompareAndSet(varHandle);
}
diff --git a/src/test/examplesJava9/varhandle/InstanceObjectField.java b/src/test/examplesJava9/varhandle/InstanceObjectField.java
index ed7f198..0b19a76 100644
--- a/src/test/examplesJava9/varhandle/InstanceObjectField.java
+++ b/src/test/examplesJava9/varhandle/InstanceObjectField.java
@@ -298,6 +298,143 @@
}
}
+ public static void testSetReleaseGet(VarHandle varHandle) {
+ System.out.println("testSetReleaseGet");
+
+ InstanceObjectField instance = new InstanceObjectField();
+
+ System.out.println(varHandle.get(instance));
+ A a1 = new A(1);
+ varHandle.setRelease(instance, a1);
+ System.out.println(varHandle.get(instance));
+ System.out.println(varHandle.get(instance) == a1);
+ A a2 = new A(2);
+ varHandle.setRelease(instance, a2);
+ System.out.println(varHandle.get(instance));
+ System.out.println(varHandle.get(instance) == a2);
+
+ Object o;
+ {
+ int i;
+ varHandle.setRelease(instance, 1);
+ System.out.println(varHandle.get(instance));
+ System.out.println((int) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Integer);
+ i = (int) varHandle.get(instance);
+ System.out.println(i == 1);
+ varHandle.setRelease(instance, Integer.valueOf(2));
+ System.out.println(varHandle.get(instance));
+ System.out.println((int) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Integer);
+ i = (int) varHandle.get(instance);
+ System.out.println(i == 2);
+ }
+ {
+ long l;
+ varHandle.setRelease(instance, 3L);
+ System.out.println(varHandle.get(instance));
+ System.out.println((long) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Long);
+ l = (long) varHandle.get(instance);
+ System.out.println(l == 3L);
+ varHandle.setRelease(instance, Long.valueOf(4L));
+ System.out.println(varHandle.get(instance));
+ System.out.println((long) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Long);
+ l = (long) varHandle.get(instance);
+ System.out.println(l == 4L);
+ }
+ {
+ byte b;
+ varHandle.setRelease(instance, (byte) 5);
+ System.out.println(varHandle.get(instance));
+ System.out.println((byte) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Byte);
+ b = (byte) varHandle.get(instance);
+ System.out.println(b == (byte) 5);
+ varHandle.setRelease(instance, Byte.valueOf((byte) 6));
+ System.out.println(varHandle.get(instance));
+ System.out.println((byte) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Byte);
+ b = (byte) varHandle.get(instance);
+ System.out.println(b == 6);
+ }
+ {
+ short s;
+ varHandle.setRelease(instance, (short) 7);
+ System.out.println(varHandle.get(instance));
+ System.out.println((short) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Short);
+ s = (short) varHandle.get(instance);
+ System.out.println(s == (short) 7);
+ varHandle.setRelease(instance, Short.valueOf((short) 8));
+ System.out.println(varHandle.get(instance));
+ System.out.println((short) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Short);
+ s = (short) varHandle.get(instance);
+ System.out.println(s == 8);
+ }
+ {
+ float f;
+ varHandle.setRelease(instance, (float) 9.0f);
+ System.out.println(varHandle.get(instance));
+ System.out.println((float) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Float);
+ f = (float) varHandle.get(instance);
+ System.out.println(f == (float) 9.0f);
+ varHandle.setRelease(instance, Float.valueOf(10.0f));
+ System.out.println(varHandle.get(instance));
+ System.out.println((float) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Float);
+ f = (float) varHandle.get(instance);
+ System.out.println(f == 10.0f);
+ }
+ {
+ double d;
+ varHandle.setRelease(instance, (double) 11.0);
+ System.out.println(varHandle.get(instance));
+ System.out.println((double) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Double);
+ d = (double) varHandle.get(instance);
+ System.out.println(d == (double) 11.0);
+ varHandle.setRelease(instance, Double.valueOf(12.0));
+ System.out.println(varHandle.get(instance));
+ System.out.println((double) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Double);
+ d = (double) varHandle.get(instance);
+ System.out.println(d == 12.0);
+ }
+ {
+ char c;
+ varHandle.setRelease(instance, 'A');
+ System.out.println(varHandle.get(instance));
+ System.out.println((char) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Character);
+ c = (char) varHandle.get(instance);
+ System.out.println(c == 'A');
+ varHandle.setRelease(instance, Character.valueOf('B'));
+ System.out.println(varHandle.get(instance));
+ System.out.println((char) varHandle.get(instance));
+ o = varHandle.get(instance);
+ System.out.println(o instanceof Character);
+ c = (char) varHandle.get(instance);
+ System.out.println(c == 'B');
+ }
+ }
+
public static void testCompareAndSet(VarHandle varHandle) {
System.out.println("testCompareAndSet");
@@ -494,6 +631,7 @@
MethodHandles.lookup().findVarHandle(InstanceObjectField.class, "field", Object.class);
testSetGet(varHandle);
testSetVolatileGetVolatile(varHandle);
+ testSetReleaseGet(varHandle);
testCompareAndSet(varHandle);
testWeakCompareAndSet(varHandle);
testReturnValueClassCastException(varHandle);
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java
index bf937e2..f6c9334 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java
@@ -36,6 +36,8 @@
+ TEST_SET_EXPECTED_OUTPUT
+ "testSetVolatile\n"
+ TEST_SET_EXPECTED_OUTPUT
+ + "testSetRelease\n"
+ + TEST_SET_EXPECTED_OUTPUT
+ "testCompareAndSet\n"
+ TEST_COMPAREANDSET_EXPECTED_OUTPUT
+ "testWeakCompareAndSet\n"
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java
index 8ad1d56..a32e832 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java
@@ -36,6 +36,8 @@
+ TEST_SET_EXPECTED_OUTPUT
+ "testSetVolatile\n"
+ TEST_SET_EXPECTED_OUTPUT
+ + "testSetRelease\n"
+ + TEST_SET_EXPECTED_OUTPUT
+ "testCompareAndSet\n"
+ TEST_COMPAREANDSET_EXPECTED_OUTPUT
+ "testWeakCompareAndSet\n"
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
index 3adf5ec..7b2f8ba 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
@@ -41,6 +41,8 @@
+ TEST_SET_EXPECTED_OUTPUT
+ "testSetVolatile\n"
+ TEST_SET_EXPECTED_OUTPUT
+ + "testSetRelease\n"
+ + TEST_SET_EXPECTED_OUTPUT
+ "testCompareAndSet\n"
+ TEST_COMPAREANDSET_EXPECTED_OUTPUT
+ "testWeakCompareAndSet\n"
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 36f86de..0dd40b9 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
@@ -35,6 +35,8 @@
+ TEST_SET_EXPECTED_OUTPUT
+ "testSetVolatile\n"
+ TEST_SET_EXPECTED_OUTPUT
+ + "testSetRelease\n"
+ + TEST_SET_EXPECTED_OUTPUT
+ "testCompareAndSet\n"
+ TEST_COMPAREANDSET_EXPECTED_OUTPUT
+ "testWeakCompareAndSet\n"
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 c57bf6d..e9b1bc3 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
@@ -35,6 +35,8 @@
+ TEST_SET_EXPECTED_OUTPUT
+ "testSetVolatile\n"
+ TEST_SET_EXPECTED_OUTPUT
+ + "testSetRelease\n"
+ + TEST_SET_EXPECTED_OUTPUT
+ "testCompareAndSet\n"
+ TEST_COMPAREANDSET_EXPECTED_OUTPUT
+ "testWeakCompareAndSet\n"
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
index 2b9a521..8e136f4 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
@@ -33,6 +33,8 @@
+ TEST_GET_SET_EXPECTED_OUTPUT
+ "testSetVolatileGetVolatile\n"
+ TEST_GET_SET_EXPECTED_OUTPUT
+ + "testSetReleaseGet\n"
+ + TEST_GET_SET_EXPECTED_OUTPUT
+ "testCompareAndSet\n"
+ TEST_COMPAREANDSET_EXPECTED_OUTPUT
+ "testWeakCompareAndSet\n"
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 a3e2880..a83c3bb 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
@@ -77,6 +77,18 @@
throw new RuntimeException("Stub called.");
}
+ public void putOrderedInt(Object obj, long offset, int newValue) {
+ throw new RuntimeException("Stub called.");
+ }
+
+ public void putOrderedLong(Object obj, long offset, long newValue) {
+ throw new RuntimeException("Stub called.");
+ }
+
+ public void putOrderedObject(Object obj, long offset, Object newValue) {
+ throw new RuntimeException("Stub called.");
+ }
+
public int arrayBaseOffset(Class<?> clazz) {
throw new RuntimeException("Stub called.");
}
@@ -342,6 +354,37 @@
}
}
+ // setRelease variants.
+ void setRelease(Object ct1, Object newValue) {
+ if (type == int.class) {
+ setReleaseInt(ct1, toIntIfPossible(newValue, false));
+ } else if (type == long.class) {
+ setReleaseLong(ct1, toLongIfPossible(newValue, false));
+ } else {
+ U.putOrderedObject(ct1, offset, newValue);
+ }
+ }
+
+ void setReleaseInt(Object ct1, int newValue) {
+ if (type == int.class) {
+ U.putOrderedInt(ct1, offset, newValue);
+ } else if (type == long.class) {
+ U.putOrderedLong(ct1, offset, newValue);
+ } else {
+ setRelease(ct1, newValue);
+ }
+ }
+
+ void setReleaseLong(Object ct1, long newValue) {
+ if (type == long.class) {
+ U.putOrderedLong(ct1, offset, newValue);
+ } else if (type == int.class) {
+ throw desugarWrongMethodTypeException();
+ } else {
+ U.putOrderedObject(ct1, offset, Long.valueOf(newValue));
+ }
+ }
+
boolean compareAndSet(Object ct1, Object expectedValue, Object newValue) {
if (type == int.class) {
return U.compareAndSwapInt(
@@ -572,6 +615,37 @@
U.putLongVolatile(ct1, elementOffset, newValue);
}
+ // setRelease array variants.
+ void setReleaseArray(Object ct1, int ct2, Object newValue) {
+ if (!recv.isArray() || recv != ct1.getClass()) {
+ throw new UnsupportedOperationException();
+ }
+ long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+ if (recv == int[].class) {
+ U.putOrderedInt(ct1, elementOffset, toIntIfPossible(newValue, false));
+ } else if (recv == long[].class) {
+ U.putOrderedLong(ct1, elementOffset, toLongIfPossible(newValue, false));
+ } else {
+ U.putOrderedObject(ct1, elementOffset, newValue);
+ }
+ }
+
+ void setReleaseArrayInt(int[] ct1, int ct2, int newValue) {
+ if (recv != int[].class) {
+ throw new UnsupportedOperationException();
+ }
+ long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+ U.putOrderedInt(ct1, elementOffset, newValue);
+ }
+
+ void setReleaseArrayLong(long[] ct1, int ct2, long newValue) {
+ if (recv != long[].class) {
+ throw new UnsupportedOperationException();
+ }
+ long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+ U.putOrderedLong(ct1, elementOffset, newValue);
+ }
+
// compareAndSet array variants.
boolean compareAndSetArray(Object ct1, int ct2, Object expetedValue, Object newValue) {
if (!recv.isArray() || recv != ct1.getClass()) {
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 72dac27..1823867 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
@@ -231,7 +231,13 @@
ImmutableSet.of("InBox", "Int", "Long", "Array", "ArrayInBox", "ArrayInt", "ArrayLong");
for (String prefix :
ImmutableList.of(
- "get", "set", "compareAndSet", "weakCompareAndSet", "getVolatile", "setVolatile")) {
+ "get",
+ "set",
+ "compareAndSet",
+ "weakCompareAndSet",
+ "getVolatile",
+ "setVolatile",
+ "setRelease")) {
if (name.startsWith(prefix)) {
String postfix = name.substring(prefix.length());
if (postfixes.contains(postfix)) {