VarHandle desugar: Add support for array element var handles

Support is limited to single dimension arrays of int, long and reference
types.

Bug: b/247076137
Change-Id: Ic6485ca4bf11610efb24052793594526688f355e
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
index df1ba99..8bd0077 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
@@ -155,7 +155,9 @@
 
     @Override
     public void acceptVarHandleDesugaringClass(DexProgramClass clazz) {
-      methodProcessor.scheduleDesugaredMethodsForProcessing(clazz.programMethods());
+      clazz
+          .programMethods()
+          .forEach(method -> methodProcessor.scheduleMethodForProcessing(method, this));
     }
 
     @Override
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 b83c526..6aaf59d 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
@@ -258,24 +258,36 @@
           && method.getArity() == 0
           && invoke.isInvokeStatic()) {
         return computeMethodHandlesLookup(factory);
+      } else if (method.getName().equals(factory.createString("arrayElementVarHandle"))
+          && method.getReturnType() == factory.varHandleType
+          && method.getArity() == 1
+          && method.getParameter(0) == factory.classType
+          && invoke.isInvokeStatic()) {
+        return computeMethodHandlesArrayElementVarHandle(factory);
       } else {
         return DesugarDescription.nothing();
       }
     }
 
     if (method.getHolderType() == factory.varHandleType) {
+      if (!invoke.isInvokeVirtual()) {
+        // Right now only <init> should be hit from MethodHandles.Lookup desugaring creating
+        // a VarHandle instance.
+        assert invoke.isInvokeSpecial();
+        return DesugarDescription.nothing();
+      }
       assert invoke.isInvokeVirtual();
       DexString name = method.getName();
       int arity = method.getProto().getArity();
       // TODO(b/247076137): Support two coordinates (array element VarHandle).
       if (name.equals(factory.compareAndSetString)) {
-        assert arity == 3;
+        assert arity == 3 || arity == 4;
         return computeDesugarSignaturePolymorphicMethod(invoke, arity - 2);
       } else if (name.equals(factory.getString)) {
-        assert arity == 1;
+        assert arity == 1 || arity == 2;
         return computeDesugarSignaturePolymorphicMethod(invoke, arity);
       } else if (name.equals(factory.setString)) {
-        assert arity == 2;
+        assert arity == 2 || arity == 3;
         return computeDesugarSignaturePolymorphicMethod(invoke, arity - 1);
       } else {
         // TODO(b/247076137): Insert runtime exception - unsupported VarHandle operation.
@@ -308,6 +320,29 @@
         .build();
   }
 
+  public DesugarDescription computeMethodHandlesArrayElementVarHandle(DexItemFactory factory) {
+    return DesugarDescription.builder()
+        .setDesugarRewrite(
+            (freshLocalProvider,
+                localStackAllocator,
+                eventConsumer,
+                context,
+                methodProcessingContext,
+                dexItemFactory) ->
+                ImmutableList.of(
+                    new CfNew(factory.varHandleType),
+                    new CfStackInstruction(Opcode.DupX1),
+                    new CfStackInstruction(Opcode.Swap),
+                    new CfInvoke(
+                        Opcodes.INVOKESPECIAL,
+                        factory.createMethod(
+                            factory.varHandleType,
+                            factory.createProto(factory.voidType, factory.classType),
+                            factory.constructorMethodName),
+                        false)))
+        .build();
+  }
+
   public DesugarDescription computeDesugarSignaturePolymorphicMethod(
       CfInvoke invoke, int coordinates) {
     return DesugarDescription.builder()
@@ -338,24 +373,38 @@
       CfInvoke invoke, int coordinates, FreshLocalProvider freshLocalProvider) {
     assert invoke.isInvokeVirtual();
     // TODO(b/247076137): Support two coordinates (array element VarHandle).
-    assert coordinates == 1 && invoke.getMethod().getProto().getArity() >= coordinates;
+    assert (coordinates == 1 || coordinates == 2)
+        && invoke.getMethod().getProto().getArity() >= coordinates;
     // Only support zero, one and two arguments after coordinates.
     int nonCoordinateArguments = invoke.getMethod().getProto().getArity() - coordinates;
     assert nonCoordinateArguments <= 2;
 
     DexProto proto = invoke.getMethod().getProto();
     DexType ct1Type = invoke.getMethod().getProto().getParameter(0);
-    if (!ct1Type.isClassType()) {
+    if (!ct1Type.isClassType() && !ct1Type.isArrayType()) {
       return null;
     }
+    DexType ct1ElementType = null;
+    if (ct1Type.isArrayType()) {
+      ct1ElementType = ct1Type.toDimensionMinusOneType(factory);
+      if (ct1ElementType != factory.intType
+          && ct1ElementType != factory.longType
+          && !ct1ElementType.isReferenceType()) {
+        return null;
+      }
+      DexType ct2Type = invoke.getMethod().getProto().getParameter(1);
+      if (ct2Type != factory.intType) {
+        return null;
+      }
+    }
 
     // Convert the arguments by boxing except for primitive int and long.
     ImmutableList.Builder<CfInstruction> builder = ImmutableList.builder();
     List<DexType> newParameters = new ArrayList<>(proto.parameters.size());
-    newParameters.add(factory.objectType);
+    DexType argumentType = null;
+    boolean hasWideArgument = false;
     if (nonCoordinateArguments > 0) {
-      DexType argumentType = objectOrPrimitiveParameterType(proto.parameters.get(coordinates));
-      boolean hasWideArgument = false;
+      argumentType = objectOrPrimitiveParameterType(proto.parameters.get(coordinates));
       for (int i = coordinates; i < proto.parameters.size(); i++) {
         hasWideArgument = hasWideArgument || proto.parameters.get(i).isWideType();
         DexType type = objectOrPrimitiveParameterType(proto.parameters.get(i));
@@ -364,51 +413,78 @@
         }
       }
       assert isPrimitiveThatIsNotBoxed(argumentType) || argumentType == factory.objectType;
-      // Ensure all arguments are boxed.
-      for (int i = coordinates; i < proto.parameters.size(); i++) {
-        if (argumentType.isPrimitiveType()) {
-          newParameters.add(argumentType);
-        } else {
-          boolean lastArgument = i == proto.parameters.size() - 1;
-          // Pass all boxed objects as Object.
-          newParameters.add(factory.objectType);
-          if (!proto.parameters.get(i).isPrimitiveType()) {
-            continue;
-          }
-          int local = -1;
-          // For boxing of the second to last argument (we only have one or two) bring it to TOS.
-          if (!lastArgument) {
-            if (hasWideArgument) {
-              local = freshLocalProvider.getFreshLocal(2);
-              builder.add(new CfStore(ValueType.fromDexType(proto.parameters.get(i + 1)), local));
-            } else {
-              builder.add(new CfStackInstruction(Opcode.Swap));
-            }
-          }
-          builder.add(
-              new CfInvoke(
-                  Opcodes.INVOKESTATIC,
-                  factory.getBoxPrimitiveMethod(proto.parameters.get(i)),
-                  false));
-          // When boxing of the second to last argument (we only have one or two) bring last
-          // argument back to TOS.
-          if (!lastArgument) {
-            if (hasWideArgument) {
-              assert local != -1;
-              builder.add(new CfLoad(ValueType.fromDexType(proto.parameters.get(i + 1)), local));
-            } else {
-              builder.add(new CfStackInstruction(Opcode.Swap));
-            }
-          }
-        }
-      }
     }
-    assert newParameters.size() == proto.parameters.size();
     DexString name = invoke.getMethod().getName();
     DexType returnType =
         factory.polymorphicMethods.varHandleCompareAndSetMethodNames.contains(name)
             ? proto.returnType
             : objectOrPrimitiveReturnType(proto.returnType);
+
+    if (coordinates == 1) {
+      newParameters.add(factory.objectType);
+    } else {
+      assert coordinates == 2;
+      // For array VarHandle only use the method with primitive arguments if all relevant parts of
+      // the signature has the same primitive type.
+      assert ct1ElementType != null;
+      boolean usePrimitiveArray =
+          ct1ElementType.isPrimitiveType()
+              && (argumentType == null || argumentType == ct1ElementType)
+              && (factory.polymorphicMethods.varHandleCompareAndSetMethodNames.contains(name)
+                  || returnType.isVoidType()
+                  || returnType == ct1ElementType);
+      newParameters.add(usePrimitiveArray ? ct1Type : factory.objectType);
+      newParameters.add(factory.intType);
+      if (!usePrimitiveArray) {
+        if (argumentType != null) {
+          argumentType = factory.objectType;
+        }
+        if (!factory.polymorphicMethods.varHandleCompareAndSetMethodNames.contains(name)
+            && !returnType.isVoidType()) {
+          returnType = factory.objectType;
+        }
+      }
+    }
+
+    // Ensure all arguments are boxed if required.
+    for (int i = coordinates; i < proto.parameters.size(); i++) {
+      if (argumentType.isPrimitiveType()) {
+        newParameters.add(argumentType);
+      } else {
+        boolean lastArgument = i == proto.parameters.size() - 1;
+        // Pass all boxed objects as Object.
+        newParameters.add(factory.objectType);
+        if (!proto.parameters.get(i).isPrimitiveType()) {
+          continue;
+        }
+        int local = -1;
+        // For boxing of the second to last argument (we only have one or two) bring it to TOS.
+        if (!lastArgument) {
+          if (hasWideArgument) {
+            local = freshLocalProvider.getFreshLocal(2);
+            builder.add(new CfStore(ValueType.fromDexType(proto.parameters.get(i + 1)), local));
+          } else {
+            builder.add(new CfStackInstruction(Opcode.Swap));
+          }
+        }
+        builder.add(
+            new CfInvoke(
+                Opcodes.INVOKESTATIC,
+                factory.getBoxPrimitiveMethod(proto.parameters.get(i)),
+                false));
+        // When boxing of the second to last argument (we only have one or two) bring last
+        // argument back to TOS.
+        if (!lastArgument) {
+          if (hasWideArgument) {
+            assert local != -1;
+            builder.add(new CfLoad(ValueType.fromDexType(proto.parameters.get(i + 1)), local));
+          } else {
+            builder.add(new CfStackInstruction(Opcode.Swap));
+          }
+        }
+      }
+    }
+    assert newParameters.size() == proto.parameters.size();
     if (proto.returnType != returnType) {
       if (proto.returnType.isPrimitiveType()) {
         builder.add(new CfConstClass(factory.getBoxedForPrimitiveType(proto.returnType)));
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 9f1ba61..c2673ba 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
@@ -8,6 +8,7 @@
 
 package com.android.tools.r8.ir.desugar.varhandle;
 
+import com.android.tools.r8.cf.code.CfArithmeticBinop;
 import com.android.tools.r8.cf.code.CfCheckCast;
 import com.android.tools.r8.cf.code.CfConstClass;
 import com.android.tools.r8.cf.code.CfConstNull;
@@ -54,6 +55,7 @@
     factory.createSynthesizedType("Ljava/lang/ClassCastException;");
     factory.createSynthesizedType("Ljava/lang/Double;");
     factory.createSynthesizedType("Ljava/lang/Float;");
+    factory.createSynthesizedType("Ljava/lang/IllegalArgumentException;");
     factory.createSynthesizedType("Ljava/lang/Integer;");
     factory.createSynthesizedType("Ljava/lang/Long;");
     factory.createSynthesizedType("Ljava/lang/RuntimeException;");
@@ -101,23 +103,122 @@
                         builder.getType(), factory.longType, factory.createString("offset")))
                 .setAccessFlags(FieldAccessFlags.createPublicFinalSynthetic())
                 .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedField.syntheticBuilder()
+                .setField(
+                    factory.createField(
+                        builder.getType(),
+                        factory.longType,
+                        factory.createString("arrayIndexScale")))
+                .setAccessFlags(FieldAccessFlags.createPublicFinalSynthetic())
+                .disableAndroidApiLevelCheck()
                 .build()));
     DexMethod toIntIfPossible =
         factory.createMethod(
             builder.getType(),
             factory.createProto(factory.intType, factory.objectType, factory.booleanType),
             factory.createString("toIntIfPossible"));
-    DexMethod get =
-        factory.createMethod(
-            builder.getType(),
-            factory.createProto(factory.objectType, factory.objectType),
-            factory.createString("get"));
     DexMethod compareAndSet =
         factory.createMethod(
             builder.getType(),
             factory.createProto(
                 factory.booleanType, factory.objectType, factory.objectType, factory.objectType),
             factory.createString("compareAndSet"));
+    DexMethod getArrayInBox =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.objectType,
+                factory.objectType,
+                factory.intType,
+                factory.createType(factory.createString("Ljava/lang/Class;"))),
+            factory.createString("get"));
+    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(),
+            factory.createProto(
+                factory.objectType,
+                factory.intType,
+                factory.createType(factory.createString("Ljava/lang/Class;"))),
+            factory.createString("boxIntIfPossible"));
+    DexMethod desugarWrongMethodTypeException =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.createType(factory.createString("Ljava/lang/RuntimeException;"))),
+            factory.createString("desugarWrongMethodTypeException"));
+    DexMethod setArrayLong =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.voidType,
+                factory.createType(factory.createString("[J")),
+                factory.intType,
+                factory.longType),
+            factory.createString("set"));
+    DexMethod getInt =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.intType, 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 getLong =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.longType, factory.objectType),
+            factory.createString("get"));
+    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 get =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.objectType, factory.objectType),
+            factory.createString("get"));
+    DexMethod compareAndSetArrayInt =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.booleanType,
+                factory.createType(factory.createString("[I")),
+                factory.intType,
+                factory.intType,
+                factory.intType),
+            factory.createString("compareAndSet"));
     DexMethod constructor_1 =
         factory.createMethod(
             builder.getType(),
@@ -138,11 +239,19 @@
                 factory.createType(factory.createString("Ljava/lang/String;")),
                 factory.createType(factory.createString("Ljava/lang/Class;"))),
             factory.createString("<init>"));
-    DexMethod setLong =
+    DexMethod arrayRequiringNativeSupport =
         factory.createMethod(
             builder.getType(),
-            factory.createProto(factory.voidType, factory.objectType, factory.longType),
-            factory.createString("set"));
+            factory.createProto(factory.createType(factory.createString("Ljava/lang/String;"))),
+            factory.createString("arrayRequiringNativeSupport"));
+    DexMethod boxLongIfPossible =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.objectType,
+                factory.longType,
+                factory.createType(factory.createString("Ljava/lang/Class;"))),
+            factory.createString("boxLongIfPossible"));
     DexMethod compareAndSetLong =
         factory.createMethod(
             builder.getType(),
@@ -159,35 +268,38 @@
             builder.getType(),
             factory.createProto(factory.voidType, factory.objectType, factory.objectType),
             factory.createString("set"));
+    DexMethod getArrayInt =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.intType, factory.createType(factory.createString("[I")), factory.intType),
+            factory.createString("get"));
+    DexMethod setArray =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.voidType, factory.objectType, factory.intType, factory.objectType),
+            factory.createString("set"));
     DexMethod compareAndSetInt =
         factory.createMethod(
             builder.getType(),
             factory.createProto(
                 factory.booleanType, factory.objectType, factory.intType, factory.intType),
             factory.createString("compareAndSet"));
-    DexMethod desugarWrongMethodTypeException =
+    DexMethod compareAndSetArray =
         factory.createMethod(
             builder.getType(),
             factory.createProto(
-                factory.createType(factory.createString("Ljava/lang/RuntimeException;"))),
-            factory.createString("desugarWrongMethodTypeException"));
-    DexMethod getInt =
-        factory.createMethod(
-            builder.getType(),
-            factory.createProto(factory.intType, factory.objectType),
-            factory.createString("get"));
-    DexMethod getLong =
-        factory.createMethod(
-            builder.getType(),
-            factory.createProto(factory.longType, factory.objectType),
-            factory.createString("get"));
-    DexMethod getInBox =
-        factory.createMethod(
-            builder.getType(),
-            factory.createProto(
+                factory.booleanType,
                 factory.objectType,
+                factory.intType,
                 factory.objectType,
-                factory.createType(factory.createString("Ljava/lang/Class;"))),
+                factory.objectType),
+            factory.createString("compareAndSet"));
+    DexMethod getArray =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.objectType, factory.objectType, factory.intType),
             factory.createString("get"));
     builder.setDirectMethods(
         ImmutableList.of(
@@ -218,6 +330,104 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(compareAndSet)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_compareAndSet(factory, compareAndSet))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getArrayInBox)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getArrayInBox(factory, getArrayInBox))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(setArrayInt)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_setArrayInt(factory, setArrayInt))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(setLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_setLong(factory, setLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(boxIntIfPossible)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_boxIntIfPossible(factory, boxIntIfPossible))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(desugarWrongMethodTypeException)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(
+                    DesugarVarHandle_desugarWrongMethodTypeException(
+                        factory, desugarWrongMethodTypeException))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(setArrayLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_setArrayLong(factory, setArrayLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getInt)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getInt(factory, getInt))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getArrayLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getArrayLong(factory, getArrayLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getLong(factory, getLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(compareAndSetArrayLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_compareAndSetArrayLong(factory, compareAndSetArrayLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getInBox)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getInBox(factory, getInBox))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(get)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -226,11 +436,11 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
-                .setMethod(compareAndSet)
+                .setMethod(compareAndSetArrayInt)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
                         Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
-                .setCode(DesugarVarHandle_compareAndSet(factory, compareAndSet))
+                .setCode(DesugarVarHandle_compareAndSetArrayInt(factory, compareAndSetArrayInt))
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
@@ -242,11 +452,21 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
-                .setMethod(setLong)
+                .setMethod(arrayRequiringNativeSupport)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
                         Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
-                .setCode(DesugarVarHandle_setLong(factory, setLong))
+                .setCode(
+                    DesugarVarHandle_arrayRequiringNativeSupport(
+                        factory, arrayRequiringNativeSupport))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(boxLongIfPossible)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_boxLongIfPossible(factory, boxLongIfPossible))
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
@@ -274,6 +494,22 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(getArrayInt)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getArrayInt(factory, getArrayInt))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(setArray)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_setArray(factory, setArray))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(compareAndSetInt)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -282,37 +518,19 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
-                .setMethod(desugarWrongMethodTypeException)
+                .setMethod(compareAndSetArray)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
                         Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
-                .setCode(
-                    DesugarVarHandle_desugarWrongMethodTypeException(
-                        factory, desugarWrongMethodTypeException))
+                .setCode(DesugarVarHandle_compareAndSetArray(factory, compareAndSetArray))
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
-                .setMethod(getInt)
+                .setMethod(getArray)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
                         Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
-                .setCode(DesugarVarHandle_getInt(factory, getInt))
-                .disableAndroidApiLevelCheck()
-                .build(),
-            DexEncodedMethod.syntheticBuilder()
-                .setMethod(getLong)
-                .setAccessFlags(
-                    MethodAccessFlags.fromSharedAccessFlags(
-                        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))
+                .setCode(DesugarVarHandle_getArray(factory, getArray))
                 .disableAndroidApiLevelCheck()
                 .build()));
   }
@@ -419,10 +637,21 @@
     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();
+    CfLabel label18 = new CfLabel();
+    CfLabel label19 = new CfLabel();
     return new CfCode(
         method.holder,
-        3,
-        3,
+        4,
+        4,
         ImmutableList.of(
             label0,
             new CfLoad(ValueType.OBJECT, 0),
@@ -473,6 +702,269 @@
                     factory.createType("Lsun/misc/Unsafe;"),
                     factory.createString("U"))),
             label4,
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isArray")),
+                false),
+            new CfIf(If.Type.NE, ValueType.INT, label6),
+            label5,
+            new CfNew(factory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfNew(factory.stringBuilderType),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfConstString(factory.createString("not an array ")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("getSimpleName")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
+                false),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IllegalArgumentException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label6,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/reflect/Field;"))
+                    })),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.classType),
+                    factory.createString("getComponentType")),
+                false),
+            new CfStore(ValueType.OBJECT, 3),
+            label7,
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isArray")),
+                false),
+            new CfIf(If.Type.EQ, ValueType.INT, label10),
+            label8,
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfNew(factory.stringBuilderType),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfConstString(
+                factory.createString("Using a VarHandle for a multidimensional array ")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfLoad(ValueType.OBJECT, 0),
+            label9,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.stringType),
+                    factory.createString("arrayRequiringNativeSupport")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
+                false),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label10,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/reflect/Field;")),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPrimitive")),
+                false),
+            new CfIf(If.Type.EQ, ValueType.INT, label14),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label14),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label14),
+            label11,
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfNew(factory.stringBuilderType),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfConstString(factory.createString("Using a VarHandle for an array of type '")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            label12,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("getName")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfConstString(factory.createString("' ")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfLoad(ValueType.OBJECT, 0),
+            label13,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.stringType),
+                    factory.createString("arrayRequiringNativeSupport")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
+                false),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label14,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/reflect/Field;")),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInstanceFieldWrite(
@@ -480,7 +972,7 @@
                     factory.createType("Ljava/lang/invoke/VarHandle;"),
                     factory.classType,
                     factory.createString("recv"))),
-            label5,
+            label15,
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
@@ -495,7 +987,7 @@
                     factory.createType("Ljava/lang/invoke/VarHandle;"),
                     factory.classType,
                     factory.createString("type"))),
-            label6,
+            label16,
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInstanceFieldRead(
@@ -522,9 +1014,36 @@
                     factory.createType("Ljava/lang/invoke/VarHandle;"),
                     factory.longType,
                     factory.createString("offset"))),
-            label7,
+            label17,
+            new CfLoad(ValueType.OBJECT, 0),
+            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, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.classType),
+                    factory.createString("arrayIndexScale")),
+                false),
+            new CfNumberConversion(NumericType.INT, NumericType.LONG),
+            new CfInstanceFieldWrite(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("arrayIndexScale"))),
+            label18,
             new CfReturnVoid(),
-            label8),
+            label19),
         ImmutableList.of(),
         ImmutableList.of());
   }
@@ -543,6 +1062,7 @@
     CfLabel label10 = new CfLabel();
     CfLabel label11 = new CfLabel();
     CfLabel label12 = new CfLabel();
+    CfLabel label13 = new CfLabel();
     return new CfCode(
         method.holder,
         4,
@@ -764,8 +1284,218 @@
                     factory.longType,
                     factory.createString("offset"))),
             label11,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfConstNumber(0, ValueType.LONG),
+            new CfInstanceFieldWrite(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("arrayIndexScale"))),
+            label12,
             new CfReturnVoid(),
-            label12),
+            label13),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_arrayRequiringNativeSupport(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        1,
+        1,
+        ImmutableList.of(
+            label0,
+            new CfConstString(
+                factory.createString(
+                    "requires native VarHandle support available from Android 13. VarHandle"
+                        + " desugaring only supports single dimensional arrays of primitive"
+                        + " typesint and long and reference types.")),
+            new CfReturn(ValueType.OBJECT),
+            label1),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_boxIntIfPossible(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();
+    return new CfCode(
+        method.holder,
+        2,
+        3,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfConstClass(factory.createType("Ljava/lang/Long;")),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+            label1,
+            new CfLoad(ValueType.INT, 1),
+            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),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfConstClass(factory.createType("Ljava/lang/Float;")),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.INT, 1),
+            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),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfConstClass(factory.createType("Ljava/lang/Double;")),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label6),
+            label5,
+            new CfLoad(ValueType.INT, 1),
+            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),
+            label6,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            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(),
+            label7),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_boxLongIfPossible(
+      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,
+        2,
+        4,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstClass(factory.createType("Ljava/lang/Float;")),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+            label1,
+            new CfLoad(ValueType.LONG, 1),
+            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),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstClass(factory.createType("Ljava/lang/Double;")),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.LONG, 1),
+            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),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            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(),
+            label5),
         ImmutableList.of(),
         ImmutableList.of());
   }
@@ -964,6 +1694,454 @@
         ImmutableList.of());
   }
 
+  public static CfCode DesugarVarHandle_compareAndSetArray(
+      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();
+    return new CfCode(
+        method.holder,
+        9,
+        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 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, 4},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      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, 4},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      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, 5),
+            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, label8),
+            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, 5),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstNumber(0, ValueType.INT),
+            label5,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.booleanType),
+                    factory.createString("toIntIfPossible")),
+                false),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 4),
+            new CfConstNumber(0, ValueType.INT),
+            label6,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.booleanType),
+                    factory.createString("toIntIfPossible")),
+                false),
+            label7,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.longType,
+                        factory.intType,
+                        factory.intType),
+                    factory.createString("compareAndSwapInt")),
+                false),
+            new CfReturn(ValueType.INT),
+            label8,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      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, label13),
+            label9,
+            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.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstNumber(0, ValueType.INT),
+            label10,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.booleanType),
+                    factory.createString("toLongIfPossible")),
+                false),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 4),
+            new CfConstNumber(0, ValueType.INT),
+            label11,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.booleanType),
+                    factory.createString("toLongIfPossible")),
+                false),
+            label12,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.longType,
+                        factory.longType,
+                        factory.longType),
+                    factory.createString("compareAndSwapLong")),
+                false),
+            new CfReturn(ValueType.INT),
+            label13,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      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, 5),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfLoad(ValueType.OBJECT, 4),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.longType,
+                        factory.objectType,
+                        factory.objectType),
+                    factory.createString("compareAndSwapObject")),
+                false),
+            new CfReturn(ValueType.INT),
+            label14),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_compareAndSetArrayInt(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = 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.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, 4},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.intArrayType),
+                      FrameType.intType(),
+                      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, 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.INT, 3),
+            new CfLoad(ValueType.INT, 4),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.longType,
+                        factory.intType,
+                        factory.intType),
+                    factory.createString("compareAndSwapInt")),
+                false),
+            new CfReturn(ValueType.INT),
+            label4),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_compareAndSetArrayLong(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        8,
+        9,
+        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, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.longArrayType),
+                      FrameType.intType(),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      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, 7),
+            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, 7),
+            new CfLoad(ValueType.LONG, 3),
+            new CfLoad(ValueType.LONG, 5),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.longType,
+                        factory.longType,
+                        factory.longType),
+                    factory.createString("compareAndSwapLong")),
+                false),
+            new CfReturn(ValueType.INT),
+            label4),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode DesugarVarHandle_compareAndSetInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
@@ -1384,7 +2562,218 @@
         ImmutableList.of());
   }
 
-  public static CfCode DesugarVarHandle_getInBox(DexItemFactory factory, DexMethod method) {
+  public static CfCode DesugarVarHandle_getArray(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();
+    return new CfCode(
+        method.holder,
+        6,
+        5,
+        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},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType()
+                    })),
+            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},
+                    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.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, 3),
+            label3,
+            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, 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, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getInt")),
+                false),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.createType("Ljava/lang/Integer;"), factory.intType),
+                    factory.createString("valueOf")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label5,
+            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.intType(),
+                      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/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            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, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLong")),
+                false),
+            new CfNumberConversion(NumericType.LONG, NumericType.INT),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.createType("Ljava/lang/Integer;"), factory.intType),
+                    factory.createString("valueOf")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label7,
+            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.intType(),
+                      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, 3),
+            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),
+            label8),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getArrayInBox(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1399,13 +2788,306 @@
     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,
+        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 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.classType)
+                    })),
+            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.classType)
+                    })),
+            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("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label5),
+            label4,
+            new CfLoad(ValueType.OBJECT, 0),
+            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 CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getInt")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.intType, factory.classType),
+                    factory.createString("boxIntIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            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.classType),
+                      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/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label7),
+            label6,
+            new CfLoad(ValueType.OBJECT, 0),
+            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 CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLong")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.longType, factory.classType),
+                    factory.createString("boxLongIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            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.classType),
+                      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 CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObject")),
+                false),
+            new CfStore(ValueType.OBJECT, 6),
+            label8,
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfInstanceOf(factory.createType("Ljava/lang/Integer;")),
+            new CfIf(If.Type.EQ, ValueType.INT, label10),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstClass(factory.createType("Ljava/lang/Integer;")),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label10),
+            label9,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfCheckCast(factory.createType("Ljava/lang/Integer;")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("intValue")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.intType, factory.classType),
+                    factory.createString("boxIntIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label10,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfInstanceOf(factory.createType("Ljava/lang/Long;")),
+            new CfIf(If.Type.EQ, ValueType.INT, label12),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstClass(factory.createType("Ljava/lang/Long;")),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label12),
+            label11,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfCheckCast(factory.createType("Ljava/lang/Long;")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType),
+                    factory.createString("longValue")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.longType, factory.classType),
+                    factory.createString("boxLongIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label12,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfReturn(ValueType.OBJECT),
+            label13),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getArrayInt(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
         5,
         ImmutableList.of(
             label0,
@@ -1414,15 +3096,177 @@
                 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},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.intArrayType),
+                      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, 3),
+            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, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getInt")),
+                false),
+            new CfReturn(ValueType.INT),
+            label4),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getArrayLong(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        5,
+        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},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.longArrayType),
+                      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, 3),
+            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, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLong")),
+                false),
+            new CfReturn(ValueType.LONG),
+            label4),
+        ImmutableList.of(),
+        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();
+    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, label9),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
             new CfInstanceFieldRead(
                 factory.createField(
                     factory.createType("Ljava/lang/invoke/VarHandle;"),
@@ -1442,94 +3286,16 @@
                     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")),
+                    factory.createProto(factory.objectType, factory.intType, factory.classType),
+                    factory.createString("boxIntIfPossible")),
                 false),
-            new CfThrow(),
-            label9,
+            new CfReturn(ValueType.OBJECT),
+            label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
@@ -1550,8 +3316,9 @@
                     factory.createType("Ljava/lang/Long;"),
                     factory.classType,
                     factory.createString("TYPE"))),
-            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label16),
-            label10,
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInstanceFieldRead(
                 factory.createField(
@@ -1572,71 +3339,16 @@
                     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")),
+                    factory.createProto(factory.objectType, factory.longType, factory.classType),
+                    factory.createString("boxLongIfPossible")),
                 false),
-            new CfThrow(),
-            label16,
+            new CfReturn(ValueType.OBJECT),
+            label4,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
@@ -1667,7 +3379,7 @@
                     factory.createString("getObject")),
                 false),
             new CfReturn(ValueType.OBJECT),
-            label17),
+            label5),
         ImmutableList.of(),
         ImmutableList.of());
   }
@@ -2067,6 +3779,407 @@
         ImmutableList.of());
   }
 
+  public static CfCode DesugarVarHandle_setArray(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("putInt")),
+                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("putLong")),
+                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("putObject")),
+                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_setArrayInt(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("putInt")),
+                false),
+            label4,
+            new CfReturnVoid(),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_setArrayLong(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("putLong")),
+                false),
+            label4,
+            new CfReturnVoid(),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode DesugarVarHandle_setInt(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 dc5ea71..c63f79d 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfInt.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfInt.java
@@ -8,7 +8,235 @@
 
 public class ArrayOfInt {
 
-  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+  private static void checkJavaLangInvokeWrongMethodTypeException(RuntimeException e) {
+    if (e.getClass().getCanonicalName().equals("java.lang.invoke.WrongMethodTypeException")
+        || e.getMessage().equals("java.lang.invoke.WrongMethodTypeException")) {
+      return;
+    }
+    throw e;
+  }
+
+  public static void testGet() {
+    System.out.println("testGet");
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);
+    int[] array = new int[2];
+
+    arrayVarHandle.set(array, 0, 1);
+    arrayVarHandle.set(array, 1, 2);
+
+    System.out.println(arrayVarHandle.get(array, 0));
+    System.out.println(arrayVarHandle.get(array, 1));
+    System.out.println((Object) arrayVarHandle.get(array, 0));
+    System.out.println((Object) arrayVarHandle.get(array, 1));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    System.out.println((float) arrayVarHandle.get(array, 0));
+    System.out.println((float) arrayVarHandle.get(array, 1));
+    System.out.println((double) arrayVarHandle.get(array, 0));
+    System.out.println((double) arrayVarHandle.get(array, 1));
+    try {
+      System.out.println((boolean) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((boolean) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
+  public static void testSet() {
+    System.out.println("testSet");
+
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);
+    int[] array = new int[2];
+
+    // int and Integer values.
+    arrayVarHandle.set(array, 0, 1);
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, 2);
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Integer.valueOf(3));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(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.set(array, 0, (byte) 5);
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, (byte) 6);
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Byte.valueOf((byte) 7));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, Byte.valueOf((byte) 8));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, '0');
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, '1');
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Character.valueOf('2'));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, Character.valueOf('3'));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, (short) 9);
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, (short) 10);
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Short.valueOf((short) 11));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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 void testCompareAndSet() {
     VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);
     int[] array = new int[2];
     arrayVarHandle.set(array, 0, 1);
@@ -20,10 +248,32 @@
     arrayVarHandle.compareAndSet(array, 1, 0, 2);
     System.out.println((int) arrayVarHandle.get(array, 0));
     System.out.println((int) arrayVarHandle.get(array, 1));
-    // TODO(sgjesse): Handle boxed.
+    // TODO(b/247076137): Handle boxed.
     // arrayVarHandle.compareAndSet(array, 1, 2, box(3));
     arrayVarHandle.compareAndSet(array, 1, 2, 3);
     System.out.println((int) arrayVarHandle.get(array, 0));
     System.out.println((int) arrayVarHandle.get(array, 1));
   }
+
+  public static void testArrayVarHandleForNonSingleDimension() {
+    System.out.println("testArrayVarHandleForNonSingleDimension");
+    try {
+      MethodHandles.arrayElementVarHandle(int.class);
+      System.out.println("Unexpected success");
+    } catch (IllegalArgumentException e) {
+      System.out.println("IllegalArgumentException");
+    }
+    try {
+      MethodHandles.arrayElementVarHandle(int[][].class);
+      System.out.println("Got array element VarHandle");
+    } catch (UnsupportedOperationException e) {
+      System.out.println("UnsupportedOperationException");
+    }
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    testGet();
+    testSet();
+    testArrayVarHandleForNonSingleDimension();
+  }
 }
diff --git a/src/test/examplesJava9/varhandle/ArrayOfLong.java b/src/test/examplesJava9/varhandle/ArrayOfLong.java
index 5d3e550..c909319 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfLong.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfLong.java
@@ -8,22 +8,259 @@
 
 public class ArrayOfLong {
 
-  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+  private static void checkJavaLangInvokeWrongMethodTypeException(RuntimeException e) {
+    if (e.getClass().getCanonicalName().equals("java.lang.invoke.WrongMethodTypeException")
+        || e.getMessage().equals("java.lang.invoke.WrongMethodTypeException")) {
+      return;
+    }
+    throw e;
+  }
+
+  public static void testGet() {
+    System.out.println("testGet");
     VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(long[].class);
     long[] array = new long[2];
+
+    arrayVarHandle.set(array, 0, 1L);
+    arrayVarHandle.set(array, 1, 2L);
+
+    System.out.println(arrayVarHandle.get(array, 0));
+    System.out.println(arrayVarHandle.get(array, 1));
+    System.out.println((Object) arrayVarHandle.get(array, 0));
+    System.out.println((Object) arrayVarHandle.get(array, 1));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    System.out.println((float) arrayVarHandle.get(array, 0));
+    System.out.println((float) arrayVarHandle.get(array, 1));
+    System.out.println((double) arrayVarHandle.get(array, 0));
+    System.out.println((double) arrayVarHandle.get(array, 1));
+    try {
+      System.out.println((boolean) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((boolean) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
+  public static void testSet() {
+    System.out.println("testSet");
+
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(long[].class);
+    long[] array = new long[2];
+
+    // long and Long values.
     arrayVarHandle.set(array, 0, 1L);
     System.out.println((long) arrayVarHandle.get(array, 0));
     System.out.println((long) arrayVarHandle.get(array, 1));
-    arrayVarHandle.compareAndSet(array, 1, 1L, 3L);
+    arrayVarHandle.set(array, 1, 2L);
     System.out.println((long) arrayVarHandle.get(array, 0));
     System.out.println((long) arrayVarHandle.get(array, 1));
-    arrayVarHandle.compareAndSet(array, 1, 0L, 2L);
+    arrayVarHandle.set(array, 0, Long.valueOf(3L));
     System.out.println((long) arrayVarHandle.get(array, 0));
     System.out.println((long) arrayVarHandle.get(array, 1));
-    // TODO(sgjesse): Handle boxed.
-    // arrayVarHandle.compareAndSet(array, 1, 2, box(3));
-    arrayVarHandle.compareAndSet(array, 1, 2L, 3L);
+    arrayVarHandle.set(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.set(array, 0, (byte) 5);
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, (byte) 6);
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Byte.valueOf((byte) 7));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, Byte.valueOf((byte) 8));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, '0');
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, '1');
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Character.valueOf('2'));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, Character.valueOf('3'));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, (short) 9);
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, (short) 10);
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Short.valueOf((short) 11));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, Short.valueOf((short) 12));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, 13);
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 1, 14);
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(array, 0, Integer.valueOf(15));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    arrayVarHandle.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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 testArrayVarHandleForNonSingleDimension() {
+    System.out.println("testArrayVarHandleForNonSingleDimension");
+    try {
+      MethodHandles.arrayElementVarHandle(int.class);
+      System.out.println("Unexpected success");
+    } catch (IllegalArgumentException e) {
+      System.out.println("IllegalArgumentException");
+    }
+    try {
+      MethodHandles.arrayElementVarHandle(int[][].class);
+      System.out.println("Got array element VarHandle");
+    } catch (UnsupportedOperationException e) {
+      System.out.println("UnsupportedOperationException");
+    }
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    testGet();
+    testSet();
+    testArrayVarHandleForNonSingleDimension();
   }
 }
diff --git a/src/test/examplesJava9/varhandle/ArrayOfObject.java b/src/test/examplesJava9/varhandle/ArrayOfObject.java
new file mode 100644
index 0000000..ab9a6bd
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/ArrayOfObject.java
@@ -0,0 +1,373 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class ArrayOfObject {
+
+  public static class A {
+
+    private final int i;
+
+    public A(int i) {
+      this.i = i;
+    }
+
+    public String toString() {
+      return "A(" + i + ")";
+    }
+  }
+
+  private static void checkJavaLangInvokeWrongMethodTypeException(RuntimeException e) {
+    if (e.getClass().getCanonicalName().equals("java.lang.invoke.WrongMethodTypeException")
+        || e.getMessage().equals("java.lang.invoke.WrongMethodTypeException")) {
+      return;
+    }
+    throw e;
+  }
+
+  public static void unsupportedGetConversion(VarHandle arrayVarHandle, Object[] array) {
+    try {
+      System.out.println((boolean) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((boolean) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
+  public static void testGet() {
+    System.out.println("testGet");
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(Object[].class);
+    Object[] array = new Object[2];
+
+    arrayVarHandle.set(array, 0, 1);
+    arrayVarHandle.set(array, 1, 2);
+
+    System.out.println(arrayVarHandle.get(array, 0));
+    System.out.println(arrayVarHandle.get(array, 1));
+    System.out.println((Object) arrayVarHandle.get(array, 0));
+    System.out.println((Object) arrayVarHandle.get(array, 1));
+    System.out.println((int) arrayVarHandle.get(array, 0));
+    System.out.println((int) arrayVarHandle.get(array, 1));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    System.out.println((float) arrayVarHandle.get(array, 0));
+    System.out.println((float) arrayVarHandle.get(array, 1));
+    System.out.println((double) arrayVarHandle.get(array, 0));
+    System.out.println((double) arrayVarHandle.get(array, 1));
+    unsupportedGetConversion(arrayVarHandle, array);
+
+    arrayVarHandle.set(array, 0, 3L);
+    arrayVarHandle.set(array, 1, 4L);
+
+    System.out.println(arrayVarHandle.get(array, 0));
+    System.out.println(arrayVarHandle.get(array, 1));
+    System.out.println((Object) arrayVarHandle.get(array, 0));
+    System.out.println((Object) arrayVarHandle.get(array, 1));
+    System.out.println((long) arrayVarHandle.get(array, 0));
+    System.out.println((long) arrayVarHandle.get(array, 1));
+    System.out.println((float) arrayVarHandle.get(array, 0));
+    System.out.println((float) arrayVarHandle.get(array, 1));
+    System.out.println((double) arrayVarHandle.get(array, 0));
+    System.out.println((double) arrayVarHandle.get(array, 1));
+    unsupportedGetConversion(arrayVarHandle, array);
+    try {
+      System.out.println((int) arrayVarHandle.get(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) arrayVarHandle.get(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
+  public static void testSet() {
+    System.out.println("testSet");
+
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(Object[].class);
+    Object[] array = new Object[2];
+
+    Object o;
+    {
+      int index = 0;
+      byte b;
+      arrayVarHandle.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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.set(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");
+
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(Object[].class);
+    Object[] array = new Object[2];
+
+    int index = 0;
+    A a1 = new A(1);
+    arrayVarHandle.compareAndSet(array, index, 0, a1);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, null, a1);
+    System.out.println(arrayVarHandle.get(array, index));
+    System.out.println(arrayVarHandle.get(array, index) == a1);
+    A a2 = new A(2);
+    arrayVarHandle.compareAndSet(array, index, a1, a2);
+    System.out.println(arrayVarHandle.get(array, index));
+    System.out.println(arrayVarHandle.get(array, index) == a2);
+
+    arrayVarHandle.compareAndSet(array, index, a2, 1);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Integer.valueOf(1), 2);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Integer.valueOf(2), Integer.valueOf(3));
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Integer.valueOf(3), 4);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, 4L, 5);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (byte) 4, 5);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (short) 4, 5);
+    System.out.println(arrayVarHandle.get(array, index));
+
+    arrayVarHandle.compareAndSet(array, index, 4, 5L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Long.valueOf(5), 6L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Long.valueOf(6), Long.valueOf(7));
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Long.valueOf(7), 8L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, 8, 9L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (byte) 8, 9);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (short) 8, 9);
+    System.out.println(arrayVarHandle.get(array, index));
+    System.out.println(arrayVarHandle.get(array, index) == a1);
+    arrayVarHandle.compareAndSet(array, index, a1, a2);
+    System.out.println(arrayVarHandle.get(array, index));
+    System.out.println(arrayVarHandle.get(array, index) == a2);
+
+    arrayVarHandle.compareAndSet(array, index, a2, 1);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Integer.valueOf(1), 2);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Integer.valueOf(2), Integer.valueOf(3));
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Integer.valueOf(3), 4);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, 4L, 5);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (byte) 4, 5);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (short) 4, 5);
+    System.out.println(arrayVarHandle.get(array, index));
+
+    arrayVarHandle.compareAndSet(array, index, 4, 5L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Long.valueOf(5), 6L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Long.valueOf(6), Long.valueOf(7));
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, Long.valueOf(7), 8L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, 8, 9L);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (byte) 8, 9);
+    System.out.println(arrayVarHandle.get(array, index));
+    arrayVarHandle.compareAndSet(array, index, (short) 8, 9);
+    System.out.println(arrayVarHandle.get(array, index));
+  }
+
+  public static void testArrayVarHandleForNonSingleDimension() {
+    System.out.println("testArrayVarHandleForNonSingleDimension");
+    try {
+      MethodHandles.arrayElementVarHandle(Object.class);
+      System.out.println("Unexpected success");
+    } catch (IllegalArgumentException e) {
+      System.out.println("IllegalArgumentException");
+    }
+    try {
+      MethodHandles.arrayElementVarHandle(Object[][].class);
+      System.out.println("Got array element VarHandle");
+    } catch (UnsupportedOperationException e) {
+      System.out.println("UnsupportedOperationException");
+    }
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    testGet();
+    testSet();
+    testCompareAndSet();
+    testArrayVarHandleForNonSingleDimension();
+  }
+}
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 d7ca20f..db63206 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
@@ -15,7 +15,74 @@
 public class VarHandleDesugaringArrayOfIntTest extends VarHandleDesugaringTestBase {
 
   private static final String EXPECTED_OUTPUT =
-      StringUtils.lines("1", "0", "1", "0", "1", "2", "1", "3");
+      StringUtils.lines(
+          "testGet",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1.0",
+          "2.0",
+          "1.0",
+          "2.0",
+          "testSet",
+          "1",
+          "0",
+          "1",
+          "2",
+          "3",
+          "2",
+          "3",
+          "4",
+          "5",
+          "4",
+          "5",
+          "6",
+          "7",
+          "6",
+          "7",
+          "8",
+          "48",
+          "8",
+          "48",
+          "49",
+          "50",
+          "49",
+          "50",
+          "51",
+          "9",
+          "51",
+          "9",
+          "10",
+          "11",
+          "10",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "11",
+          "12",
+          "testArrayVarHandleForNonSingleDimension",
+          "IllegalArgumentException");
+
   private static final String MAIN_CLASS = VarHandle.ArrayOfInt.typeName();
   private static final String JAR_ENTRY = "varhandle/ArrayOfInt.class";
 
@@ -31,6 +98,11 @@
 
   @Override
   protected String getExpectedOutputForReferenceImplementation() {
-    return EXPECTED_OUTPUT;
+    return StringUtils.lines(EXPECTED_OUTPUT.trim(), "Got array element VarHandle");
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines(EXPECTED_OUTPUT.trim(), "UnsupportedOperationException");
   }
 }
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 c3c81da..3867f1c 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
@@ -15,7 +15,76 @@
 public class VarHandleDesugaringArrayOfLongTest extends VarHandleDesugaringTestBase {
 
   private static final String EXPECTED_OUTPUT =
-      StringUtils.lines("1", "0", "1", "0", "1", "2", "1", "3");
+      StringUtils.lines(
+          "testGet",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1.0",
+          "2.0",
+          "1.0",
+          "2.0",
+          "testSet",
+          "1",
+          "0",
+          "1",
+          "2",
+          "3",
+          "2",
+          "3",
+          "4",
+          "5",
+          "4",
+          "5",
+          "6",
+          "7",
+          "6",
+          "7",
+          "8",
+          "48",
+          "8",
+          "48",
+          "49",
+          "50",
+          "49",
+          "50",
+          "51",
+          "9",
+          "51",
+          "9",
+          "10",
+          "11",
+          "10",
+          "11",
+          "12",
+          "13",
+          "12",
+          "13",
+          "14",
+          "15",
+          "14",
+          "15",
+          "16",
+          "15",
+          "16",
+          "15",
+          "16",
+          "15",
+          "16",
+          "15",
+          "16",
+          "15",
+          "16",
+          "15",
+          "16",
+          "15",
+          "16",
+          "testArrayVarHandleForNonSingleDimension",
+          "IllegalArgumentException");
+
   private static final String MAIN_CLASS = VarHandle.ArrayOfLong.typeName();
   private static final String JAR_ENTRY = "varhandle/ArrayOfLong.class";
 
@@ -31,6 +100,11 @@
 
   @Override
   protected String getExpectedOutputForReferenceImplementation() {
-    return EXPECTED_OUTPUT;
+    return StringUtils.lines(EXPECTED_OUTPUT.trim(), "Got array element VarHandle");
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines(EXPECTED_OUTPUT.trim(), "UnsupportedOperationException");
   }
 }
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
new file mode 100644
index 0000000..72439ec
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
@@ -0,0 +1,146 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringArrayOfObjectTest extends VarHandleDesugaringTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines(
+          "testGet",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1.0",
+          "2.0",
+          "1.0",
+          "2.0",
+          "3",
+          "4",
+          "3",
+          "4",
+          "3",
+          "4",
+          "3.0",
+          "4.0",
+          "3.0",
+          "4.0",
+          "testSet",
+          "5",
+          "5",
+          "true",
+          "true",
+          "6",
+          "6",
+          "true",
+          "true",
+          "7",
+          "7",
+          "true",
+          "true",
+          "8",
+          "8",
+          "true",
+          "true",
+          "9.0",
+          "9.0",
+          "true",
+          "true",
+          "10.0",
+          "10.0",
+          "true",
+          "true",
+          "11.0",
+          "11.0",
+          "true",
+          "true",
+          "12.0",
+          "12.0",
+          "true",
+          "true",
+          "A",
+          "A",
+          "true",
+          "true",
+          "B",
+          "B",
+          "true",
+          "true",
+          "testCompareAndSet",
+          "null",
+          "A(1)",
+          "true",
+          "A(2)",
+          "true",
+          "1",
+          "2",
+          "3",
+          "4",
+          "4",
+          "4",
+          "4",
+          "5",
+          "6",
+          "7",
+          "8",
+          "8",
+          "8",
+          "8",
+          "false",
+          "8",
+          "false",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "8",
+          "testArrayVarHandleForNonSingleDimension",
+          "IllegalArgumentException");
+
+  private static final String MAIN_CLASS = VarHandle.ArrayOfObject.typeName();
+  private static final List<String> JAR_ENTRIES =
+      ImmutableList.of("varhandle/ArrayOfObject.class", "varhandle/ArrayOfObject$A.class");
+
+  @Override
+  protected String getMainClass() {
+    return MAIN_CLASS;
+  }
+
+  @Override
+  protected List<String> getJarEntries() {
+    return JAR_ENTRIES;
+  }
+
+  @Override
+  protected String getExpectedOutputForReferenceImplementation() {
+    return StringUtils.lines(EXPECTED_OUTPUT.trim(), "Got array element VarHandle");
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines(EXPECTED_OUTPUT.trim(), "UnsupportedOperationException");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
index d9fc4c4..5c84a74 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
@@ -54,9 +54,4 @@
   protected String getExpectedOutputForDesugaringImplementation() {
     return StringUtils.lines("Got UnsupportedOperationException");
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
index a96b5a9..a2f3b1d 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
@@ -44,9 +44,4 @@
   protected String getExpectedOutputForDesugaringImplementation() {
     return StringUtils.lines("Got UnsupportedOperationException");
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
index 194f25f..9eccf94 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
@@ -45,9 +45,4 @@
   protected String getExpectedOutputForDesugaringImplementation() {
     return StringUtils.lines("Got UnsupportedOperationException");
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
index 457753b..db95c14 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
@@ -45,9 +45,4 @@
   protected String getExpectedOutputForDesugaringImplementation() {
     return StringUtils.lines("Got UnsupportedOperationException");
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
index f676891..1969ffb 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
@@ -93,9 +93,4 @@
   protected String getExpectedOutputForReferenceImplementation() {
     return EXPECTED_OUTPUT;
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
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 7303ec5..9794153 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
@@ -91,9 +91,4 @@
   protected String getExpectedOutputForReferenceImplementation() {
     return EXPECTED_OUTPUT;
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
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 ac43573..a7b2a30 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
@@ -147,9 +147,4 @@
     assert parameters.isDexRuntime();
     return StringUtils.lines(EXPECTED_OUTPUT.trim(), "Art implementation", "Art implementation");
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
index a5947eb..e52df14 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
@@ -44,9 +44,4 @@
   protected String getExpectedOutputForDesugaringImplementation() {
     return StringUtils.lines("Got UnsupportedOperationException");
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceStringFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceStringFieldTest.java
index f1440c1..e1beca1 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
@@ -50,9 +50,4 @@
   protected String getExpectedOutputForReferenceImplementation() {
     return EXPECTED_OUTPUT;
   }
-
-  @Override
-  protected boolean getTestWithDesugaring() {
-    return true;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
index bb4d99b..d8b0543 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
@@ -72,11 +72,6 @@
     return getExpectedOutputForReferenceImplementation();
   }
 
-  // TODO(b/247076137): Remove this when all tests can run with desugaring.
-  protected boolean getTestWithDesugaring() {
-    return false;
-  }
-
   @Test
   public void testReference() throws Throwable {
     assumeTrue(parameters.isCfRuntime());
@@ -168,8 +163,8 @@
               });
         });
     if (willDesugarVarHandle()) {
-      assertEquals(2, unsafeCompareAndSwapInt.get());
-      assertEquals(3, unsafeCompareAndSwapLong.get());
+      assertEquals(4, unsafeCompareAndSwapInt.get());
+      assertEquals(5, unsafeCompareAndSwapLong.get());
       assertEquals(1, unsafeCompareAndSwapObject.get());
     } else {
       assertEquals(0, unsafeCompareAndSwapInt.get());
@@ -182,42 +177,24 @@
   @Test
   public void testD8() throws Throwable {
     assumeTrue(parameters.isDexRuntime());
-    if (getTestWithDesugaring()) {
-      testForD8(parameters.getBackend())
-          .addProgramClassFileData(getProgramClassFileData())
-          .setMinApi(parameters.getApiLevel())
-          .addOptionsModification(options -> options.enableVarHandleDesugaring = true)
-          .run(parameters.getRuntime(), getMainClass())
-          .applyIf(
-              parameters.isDexRuntime()
-                  && parameters.asDexRuntime().getVersion().isOlderThanOrEqual(Version.V4_4_4),
-              // TODO(b/247076137): Running on 4.0.4 and 4.4.4 needs to be checked. Output seems
-              // correct, but at the same time there are VFY errors on stderr.
-              r -> r.assertFailureWithErrorThatThrows(NoSuchFieldException.class),
-              r ->
-                  r.assertSuccessWithOutput(
-                      parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.T)
-                              && parameters
-                                  .getDexRuntimeVersion()
-                                  .isNewerThanOrEqual(Version.V13_0_0)
-                          ? getExpectedOutputForArtImplementation()
-                          : getExpectedOutputForDesugaringImplementation()))
-          .inspect(this::inspect);
-    } else {
-      testForD8(parameters.getBackend())
-          .addProgramClassFileData(getProgramClassFileData())
-          .setMinApi(parameters.getApiLevel())
-          .run(parameters.getRuntime(), getMainClass())
-          .applyIf(
-              // VarHandle is available from Android 9, even though it was not a public API until
-              // 13.
-              parameters.asDexRuntime().getVersion().isOlderThanOrEqual(Version.V7_0_0),
-              r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class),
-              parameters.getApiLevel().isLessThan(AndroidApiLevel.P)
-                  || parameters.asDexRuntime().getVersion().isOlderThanOrEqual(Version.V8_1_0),
-              r -> r.assertFailure(),
-              r -> r.assertSuccessWithOutput(getExpectedOutputForArtImplementation()));
-    }
+    testForD8(parameters.getBackend())
+        .addProgramClassFileData(getProgramClassFileData())
+        .setMinApi(parameters.getApiLevel())
+        .addOptionsModification(options -> options.enableVarHandleDesugaring = true)
+        .run(parameters.getRuntime(), getMainClass())
+        .applyIf(
+            parameters.isDexRuntime()
+                && parameters.asDexRuntime().getVersion().isOlderThanOrEqual(Version.V4_4_4),
+            // TODO(b/247076137): Running on 4.0.4 and 4.4.4 needs to be checked. Output seems
+            // correct, but at the same time there are VFY errors on stderr.
+            r -> r.assertFailureWithErrorThatThrows(NoSuchFieldException.class),
+            r ->
+                r.assertSuccessWithOutput(
+                    parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.T)
+                            && parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V13_0_0)
+                        ? getExpectedOutputForArtImplementation()
+                        : getExpectedOutputForDesugaringImplementation()))
+        .inspect(this::inspect);
   }
 
   // TODO(b/247076137: Also turn on VarHandle desugaring for R8 tests.
diff --git a/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java b/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
index 0cb3d7f..cb2caed 100644
--- a/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
+++ b/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
@@ -18,6 +18,8 @@
       new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/ArrayOfInt");
   public static final JavaExampleClassProxy ArrayOfLong =
       new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/ArrayOfLong");
+  public static final JavaExampleClassProxy ArrayOfObject =
+      new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/ArrayOfObject");
 
   public static final JavaExampleClassProxy InstanceIntField =
       new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceIntField");
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 2ba4cf4..c01f4e9 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
@@ -70,6 +70,7 @@
   private final Class<?> recv;
   private final Class<?> type;
   private final long offset;
+  private final long arrayIndexScale;
 
   DesugarVarHandle(Class<?> recv, String name, Class<?> type)
       throws NoSuchFieldException, IllegalAccessException {
@@ -88,18 +89,41 @@
               + "reference types.");
     }
     this.offset = U.objectFieldOffset(recv.getDeclaredField(name));
+    this.arrayIndexScale = 0;
   }
 
   DesugarVarHandle(Class<?> arrayType) throws Exception {
     Field theUnsafe = UnsafeStub.class.getDeclaredField("theUnsafe");
     theUnsafe.setAccessible(true);
     U = (UnsafeStub) theUnsafe.get(null);
+    if (!arrayType.isArray()) {
+      throw new IllegalArgumentException("not an array " + arrayType.getSimpleName());
+    }
+    Class<?> componentType = arrayType.getComponentType();
+    if (componentType.isArray()) {
+      throw new UnsupportedOperationException(
+          "Using a VarHandle for a multidimensional array " + arrayRequiringNativeSupport());
+    }
+    if (componentType.isPrimitive() && componentType != int.class && componentType != long.class) {
+      throw new UnsupportedOperationException(
+          "Using a VarHandle for an array of type '"
+              + componentType.getName()
+              + "' "
+              + arrayRequiringNativeSupport());
+    }
     this.recv = arrayType;
     this.type = arrayType.getComponentType();
     this.offset = U.arrayBaseOffset(recv);
+    this.arrayIndexScale = U.arrayIndexScale(recv);
   }
 
   // Helpers.
+  String arrayRequiringNativeSupport() {
+    return "requires native VarHandle support available from Android 13. "
+        + "VarHandle desugaring only supports single dimensional arrays of primitive types"
+        + "int and long and reference types.";
+  }
+
   RuntimeException desugarWrongMethodTypeException() {
     return new RuntimeException("java.lang.invoke.WrongMethodTypeException");
   }
@@ -131,6 +155,29 @@
     return toIntIfPossible(value, forReturnType);
   }
 
+  Object boxIntIfPossible(int value, Class<?> expectedBox) {
+    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();
+  }
+
+  Object boxLongIfPossible(long value, Class<?> expectedBox) {
+    if (expectedBox == Float.class) {
+      return Float.valueOf(value);
+    }
+    if (expectedBox == Double.class) {
+      return Double.valueOf(value);
+    }
+    throw desugarWrongMethodTypeException();
+  }
+
   // get variants.
   Object get(Object ct1) {
     if (type == int.class) {
@@ -144,27 +191,10 @@
 
   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();
+      return boxIntIfPossible(U.getInt(ct1, offset), expectedBox);
     }
     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 boxLongIfPossible(U.getLong(ct1, offset), expectedBox);
     }
     return U.getObject(ct1, offset);
   }
@@ -248,4 +278,126 @@
     }
     return compareAndSet(ct1, expectedValue, newValue);
   }
+
+  // get array variants.
+  Object getArray(Object ct1, int ct2) {
+    if (!recv.isArray() || recv != ct1.getClass()) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    if (type == int.class) {
+      return U.getInt(ct1, elementOffset);
+    } else if (type == long.class) {
+      return (int) U.getLong(ct1, elementOffset);
+    } else {
+      return U.getObject(ct1, elementOffset);
+    }
+  }
+
+  Object getArrayInBox(Object ct1, int ct2, Class<?> expectedBox) {
+    if (!recv.isArray() || recv != ct1.getClass()) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    if (type == int.class) {
+      return boxIntIfPossible(U.getInt(ct1, elementOffset), expectedBox);
+    } else if (type == long.class) {
+      return boxLongIfPossible(U.getLong(ct1, elementOffset), expectedBox);
+    } else {
+      Object value = U.getObject(ct1, elementOffset);
+      if (value instanceof Integer && expectedBox != Integer.class) {
+        return boxIntIfPossible(((Integer) value).intValue(), expectedBox);
+      }
+      if (value instanceof Long && expectedBox != Long.class) {
+        return boxLongIfPossible(((Long) value).longValue(), expectedBox);
+      }
+      return value;
+    }
+  }
+
+  int getArrayInt(int[] ct1, int ct2) {
+    if (recv != int[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    return U.getInt(ct1, elementOffset);
+  }
+
+  long getArrayLong(long[] ct1, int ct2) {
+    if (recv != long[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    return U.getLong(ct1, elementOffset);
+  }
+
+  // get array variants.
+  void setArray(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.putInt(ct1, elementOffset, toIntIfPossible(newValue, false));
+    } else if (recv == long[].class) {
+      U.putLong(ct1, elementOffset, toLongIfPossible(newValue, false));
+    } else {
+      U.putObject(ct1, elementOffset, newValue);
+    }
+  }
+
+  void setArrayInt(int[] ct1, int ct2, int newValue) {
+    if (recv != int[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    U.putInt(ct1, elementOffset, newValue);
+  }
+
+  void setArrayLong(long[] ct1, int ct2, long newValue) {
+    if (recv != long[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    U.putLong(ct1, elementOffset, newValue);
+  }
+
+  // compareAndSet array variants.
+  boolean compareAndSetArray(Object ct1, int ct2, Object expetedValue, Object newValue) {
+    if (!recv.isArray() || recv != ct1.getClass()) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    if (recv == int[].class) {
+      return U.compareAndSwapInt(
+          ct1,
+          elementOffset,
+          toIntIfPossible(expetedValue, false),
+          toIntIfPossible(newValue, false));
+    } else if (recv == long[].class) {
+      return U.compareAndSwapLong(
+          ct1,
+          elementOffset,
+          toLongIfPossible(expetedValue, false),
+          toLongIfPossible(newValue, false));
+    } else {
+      return U.compareAndSwapObject(ct1, elementOffset, expetedValue, newValue);
+    }
+  }
+
+  boolean compareAndSetArrayInt(int[] ct1, int ct2, int expetedValue, int newValue) {
+    if (recv != int[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    return U.compareAndSwapInt(ct1, elementOffset, expetedValue, newValue);
+  }
+
+  boolean compareAndSetArrayLong(long[] ct1, int ct2, long expetedValue, long newValue) {
+    if (recv != long[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    return U.compareAndSwapLong(ct1, elementOffset, expetedValue, newValue);
+  }
 }
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 7052773..0c65df4 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
@@ -24,11 +24,13 @@
 import com.android.tools.r8.utils.FileUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.junit.Test;
@@ -220,12 +222,14 @@
   }
 
   private static String mapMethodName(String name) {
+    Set<String> postfixes =
+        ImmutableSet.of("InBox", "Int", "Long", "Array", "ArrayInBox", "ArrayInt", "ArrayLong");
     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("InBox"))) {
-        return prefix;
+      if (name.startsWith(prefix)) {
+        String postfix = name.substring(prefix.length());
+        if (postfixes.contains(postfix)) {
+          return prefix;
+        }
       }
     }
     return name;