Cleanup uses of DexValue

Change-Id: I16caa3dea8476394367b7d7b2f281d1ed7fecd3e
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index 57f8395..4b310aa 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -18,7 +18,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.graph.UseRegistry;
@@ -258,9 +257,9 @@
       }
       for (DexAnnotation annotation : method.annotations().annotations) {
         if (annotation.annotation.type == appInfo.dexItemFactory().annotationThrows) {
-          DexValueArray dexValues = (DexValueArray) annotation.annotation.elements[0].value;
+          DexValueArray dexValues = annotation.annotation.elements[0].value.asDexValueArray();
           for (DexValue dexValType : dexValues.getValues()) {
-            registerTypeReference(((DexValueType) dexValType).value);
+            registerTypeReference(dexValType.asDexValueType().value);
           }
         }
       }
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java
index efeccec..0affffd 100644
--- a/src/main/java/com/android/tools/r8/ResourceShrinker.java
+++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -174,19 +174,25 @@
     }
 
     private void processFieldValue(DexValue value) {
-      if (value instanceof DexValue.DexValueString) {
-        callback.referencedString(((DexValue.DexValueString) value).value.toString());
-      } else if (value instanceof DexValue.DexValueInt) {
-        int constantValue = ((DexValue.DexValueInt) value).getValue();
-        callback.referencedInt(constantValue);
-      } else if (value instanceof DexValue.DexValueArray) {
-        DexValue.DexValueArray arrayEncodedValue = (DexValue.DexValueArray) value;
-        for (DexValue encodedValue : arrayEncodedValue.getValues()) {
-          if (encodedValue instanceof DexValue.DexValueInt) {
-            int constantValue = ((DexValue.DexValueInt) encodedValue).getValue();
-            callback.referencedInt(constantValue);
+      switch (value.getValueKind()) {
+        case ARRAY:
+          for (DexValue elementValue : value.asDexValueArray().getValues()) {
+            if (elementValue.isDexValueInt()) {
+              callback.referencedInt(elementValue.asDexValueInt().getValue());
+            }
           }
-        }
+          break;
+
+        case INT:
+          callback.referencedInt(value.asDexValueInt().getValue());
+          break;
+
+        case STRING:
+          callback.referencedString(value.asDexValueString().value.toString());
+          break;
+
+        default:
+          // Intentionally empty.
       }
     }
 
@@ -286,22 +292,29 @@
     }
 
     private void processAnnotationValue(DexValue value) {
-      if (value instanceof DexValue.DexValueInt) {
-        DexValue.DexValueInt dexValueInt = (DexValue.DexValueInt) value;
-        callback.referencedInt(dexValueInt.value);
-      } else if (value instanceof DexValue.DexValueString) {
-        DexValue.DexValueString dexValueString = (DexValue.DexValueString) value;
-        callback.referencedString(dexValueString.value.toString());
-      } else if (value instanceof DexValue.DexValueArray) {
-        DexValue.DexValueArray dexValueArray = (DexValue.DexValueArray) value;
-        for (DexValue dexValue : dexValueArray.getValues()) {
-          processAnnotationValue(dexValue);
-        }
-      } else if (value instanceof DexValue.DexValueAnnotation) {
-        DexValue.DexValueAnnotation dexValueAnnotation = (DexValue.DexValueAnnotation) value;
-        for (DexAnnotationElement element : dexValueAnnotation.value.elements) {
-          processAnnotationValue(element.value);
-        }
+      switch (value.getValueKind()) {
+        case ANNOTATION:
+          for (DexAnnotationElement element : value.asDexValueAnnotation().value.elements) {
+            processAnnotationValue(element.value);
+          }
+          break;
+
+        case ARRAY:
+          for (DexValue elementValue : value.asDexValueArray().getValues()) {
+            processAnnotationValue(elementValue);
+          }
+          break;
+
+        case INT:
+          callback.referencedInt(value.asDexValueInt().value);
+          break;
+
+        case STRING:
+          callback.referencedString(value.asDexValueString().value.toString());
+          break;
+
+        default:
+          // Intentionally empty.
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index ef0ec1b..8f01356 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -10,14 +10,6 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueDouble;
-import com.android.tools.r8.graph.DexValue.DexValueFloat;
-import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueLong;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.ValueType;
@@ -55,26 +47,27 @@
         methodName.toString(), callSite.methodProto.toDescriptorString(lens), bsmHandle, bsmArgs);
   }
 
-  private Object decodeBootstrapArgument(DexValue dexValue, NamingLens lens) {
-    if (dexValue instanceof DexValueInt) {
-      return ((DexValueInt) dexValue).getValue();
-    } else if (dexValue instanceof DexValueLong) {
-      return ((DexValueLong) dexValue).getValue();
-    } else if (dexValue instanceof DexValueFloat) {
-      return ((DexValueFloat) dexValue).getValue();
-    } else if (dexValue instanceof DexValueDouble) {
-      return ((DexValueDouble) dexValue).getValue();
-    } else if (dexValue instanceof DexValueString) {
-      return ((DexValueString) dexValue).getValue();
-    } else if (dexValue instanceof DexValueType) {
-      return Type.getType(lens.lookupDescriptor(((DexValueType) dexValue).value).toString());
-    } else if (dexValue instanceof DexValueMethodType) {
-      return Type.getMethodType(((DexValueMethodType) dexValue).value.toDescriptorString(lens));
-    } else if (dexValue instanceof DexValueMethodHandle) {
-      return ((DexValueMethodHandle) dexValue).value.toAsmHandle(lens);
-    } else {
-      throw new Unreachable(
-          "Unsupported bootstrap argument of type " + dexValue.getClass().getSimpleName());
+  private Object decodeBootstrapArgument(DexValue value, NamingLens lens) {
+    switch (value.getValueKind()) {
+      case DOUBLE:
+        return value.asDexValueDouble().getValue();
+      case FLOAT:
+        return value.asDexValueFloat().getValue();
+      case INT:
+        return value.asDexValueInt().getValue();
+      case LONG:
+        return value.asDexValueLong().getValue();
+      case METHOD_HANDLE:
+        return value.asDexValueMethodHandle().getValue().toAsmHandle(lens);
+      case METHOD_TYPE:
+        return Type.getMethodType(value.asDexValueMethodType().getValue().toDescriptorString(lens));
+      case STRING:
+        return value.asDexValueString().getValue();
+      case TYPE:
+        return Type.getType(lens.lookupDescriptor(value.asDexValueType().value).toString());
+      default:
+        throw new Unreachable(
+            "Unsupported bootstrap argument of type " + value.getClass().getSimpleName());
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index f15e96e..a6eb1c3 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -48,10 +48,7 @@
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueKind;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
 import com.android.tools.r8.graph.DexValue.DexValueNull;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.graph.EnclosingMethodAttribute;
 import com.android.tools.r8.graph.FieldAccessFlags;
 import com.android.tools.r8.graph.InnerClassAttribute;
@@ -1244,14 +1241,14 @@
         dexReader.getUint(dexSection.offset + (Constants.TYPE_CALL_SITE_ID_ITEM_SIZE * index));
     DexEncodedArray callSiteEncodedArray = encodedArrayAt(callSiteOffset);
     DexValue[] values = callSiteEncodedArray.values;
-    assert values[0] instanceof DexValueMethodHandle;
-    assert values[1] instanceof DexValueString;
-    assert values[2] instanceof DexValueMethodType;
+    assert values[0].isDexValueMethodHandle();
+    assert values[1].isDexValueString();
+    assert values[2].isDexValueMethodType();
 
     return dexItemFactory.createCallSite(
-        ((DexValueString) values[1]).value,
-        ((DexValueMethodType) values[2]).value,
-        ((DexValueMethodHandle) values[0]).value,
+        values[1].asDexValueString().value,
+        values[2].asDexValueMethodType().value,
+        values[0].asDexValueMethodHandle().value,
         // 3 means first extra args
         Arrays.asList(Arrays.copyOfRange(values, 3, values.length)));
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index 50b4b2f..a409737 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -99,9 +99,11 @@
 
   public static DexType getEnclosingClassFromAnnotation(
       DexAnnotation annotation, DexItemFactory factory) {
-    DexValueType typeValue =
-        (DexValueType) getSystemValueAnnotationValue(factory.annotationEnclosingClass, annotation);
-    return typeValue == null ? null : typeValue.value;
+    DexValue value = getSystemValueAnnotationValue(factory.annotationEnclosingClass, annotation);
+    if (value == null) {
+      return null;
+    }
+    return value.asDexValueType().value;
   }
 
   public static DexAnnotation createEnclosingMethodAnnotation(DexMethod enclosingMethod,
@@ -112,10 +114,11 @@
 
   public static DexMethod getEnclosingMethodFromAnnotation(
       DexAnnotation annotation, DexItemFactory factory) {
-    DexValueMethod methodValue =
-        (DexValueMethod)
-            getSystemValueAnnotationValue(factory.annotationEnclosingMethod, annotation);
-    return methodValue == null ? null : methodValue.value;
+    DexValue value = getSystemValueAnnotationValue(factory.annotationEnclosingMethod, annotation);
+    if (value == null) {
+      return null;
+    }
+    return value.asDexValueMethod().value;
   }
 
   public static boolean isEnclosingClassAnnotation(DexAnnotation annotation,
@@ -159,12 +162,12 @@
     Pair<DexString, Integer> result = new Pair<>();
     for (DexAnnotationElement element : elements) {
       if (element.name == factory.createString("name")) {
-        if (element.value instanceof DexValueString) {
-          result.setFirst(((DexValueString) element.value).getValue());
+        if (element.value.isDexValueString()) {
+          result.setFirst(element.value.asDexValueString().getValue());
         }
       } else {
         assert element.name == factory.createString("accessFlags");
-        result.setSecond(((DexValueInt) element.value).getValue());
+        result.setSecond(element.value.asDexValueInt().getValue());
       }
     }
     return result;
@@ -182,14 +185,14 @@
 
   public static List<DexType> getMemberClassesFromAnnotation(
       DexAnnotation annotation, DexItemFactory factory) {
-    DexValueArray membersArray =
-        (DexValueArray) getSystemValueAnnotationValue(factory.annotationMemberClasses, annotation);
-    if (membersArray == null) {
+    DexValue value = getSystemValueAnnotationValue(factory.annotationMemberClasses, annotation);
+    if (value == null) {
       return null;
     }
+    DexValueArray membersArray = value.asDexValueArray();
     List<DexType> types = new ArrayList<>(membersArray.getValues().length);
-    for (DexValue value : membersArray.getValues()) {
-      types.add(((DexValueType) value).value);
+    for (DexValue elementValue : membersArray.getValues()) {
+      types.add(elementValue.asDexValueType().value);
     }
     return types;
   }
@@ -233,10 +236,10 @@
   }
 
   public static String getSignature(DexAnnotation signatureAnnotation) {
-    DexValueArray elements = (DexValueArray) signatureAnnotation.annotation.elements[0].value;
+    DexValueArray elements = signatureAnnotation.annotation.elements[0].value.asDexValueArray();
     StringBuilder signature = new StringBuilder();
     for (DexValue element : elements.getValues()) {
-      signature.append(((DexValueString) element).value.toString());
+      signature.append(element.asDexValueString().value.toString());
     }
     return signature.toString();
   }
@@ -349,16 +352,16 @@
       if (!value.name.toSourceString().equals("value")) {
         throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
       }
-      if (!(value.value instanceof DexValueArray)) {
+      DexValueArray existingList = value.value.asDexValueArray();
+      if (existingList == null) {
         throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
       }
-      DexValueArray existingList = (DexValueArray) value.value;
       Collection<DexType> synthesized = new ArrayList<>(existingList.values.length);
       for (DexValue element : existingList.getValues()) {
-        if (!(element instanceof DexValueType)) {
+        if (!element.isDexValueType()) {
           throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
         }
-        synthesized.add(((DexValueType) element).value);
+        synthesized.add(element.asDexValueType().value);
       }
       return synthesized;
     }
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 382f4bb..3249abf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -213,52 +213,35 @@
     private void write(List<DexValue> args) throws IOException {
       out.writeInt(args.size());
       for (DexValue arg : args) {
-        // String, Class, Integer, Long, Float, Double, MethodHandle, MethodType
-        if (arg instanceof DexValue.DexValueString) {
-          out.writeByte(0);
-          write(((DexValue.DexValueString) arg).value);
-          continue;
+        out.writeByte(arg.getValueKind().toByte());
+        switch (arg.getValueKind()) {
+          case DOUBLE:
+            out.writeDouble(arg.asDexValueDouble().value);
+            break;
+          case FLOAT:
+            out.writeFloat(arg.asDexValueFloat().value);
+            break;
+          case INT:
+            out.writeInt(arg.asDexValueInt().value);
+            break;
+          case LONG:
+            out.writeLong(arg.asDexValueLong().value);
+            break;
+          case METHOD_HANDLE:
+            write(arg.asDexValueMethodHandle().value);
+            break;
+          case METHOD_TYPE:
+            write(arg.asDexValueMethodType().value);
+            break;
+          case STRING:
+            write(arg.asDexValueString().value);
+            break;
+          case TYPE:
+            write(arg.asDexValueType().value);
+            break;
+          default:
+            assert false;
         }
-
-        if (arg instanceof DexValue.DexValueType) {
-          out.writeByte(1);
-          write(((DexValue.DexValueType) arg).value);
-          continue;
-        }
-
-        if (arg instanceof DexValue.DexValueInt) {
-          out.writeByte(2);
-          out.writeInt(((DexValue.DexValueInt) arg).value);
-          continue;
-        }
-
-        if (arg instanceof DexValue.DexValueLong) {
-          out.writeByte(3);
-          out.writeLong(((DexValue.DexValueLong) arg).value);
-          continue;
-        }
-
-        if (arg instanceof DexValue.DexValueFloat) {
-          out.writeByte(4);
-          out.writeFloat(((DexValue.DexValueFloat) arg).value);
-          continue;
-        }
-
-        if (arg instanceof DexValue.DexValueDouble) {
-          out.writeByte(5);
-          out.writeDouble(((DexValue.DexValueDouble) arg).value);
-          continue;
-        }
-
-        if (arg instanceof DexValue.DexValueMethodHandle) {
-          out.writeByte(6);
-          write(((DexValue.DexValueMethodHandle) arg).value);
-          continue;
-        }
-
-        assert arg instanceof DexValue.DexValueMethodType;
-        out.writeByte(7);
-        write(((DexValue.DexValueMethodType) arg).value);
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexValue.java b/src/main/java/com/android/tools/r8/graph/DexValue.java
index be0cf37..3472d57 100644
--- a/src/main/java/com/android/tools/r8/graph/DexValue.java
+++ b/src/main/java/com/android/tools/r8/graph/DexValue.java
@@ -102,6 +102,8 @@
 
   public static final DexValue[] EMPTY_ARRAY = {};
 
+  public abstract DexValueKind getValueKind();
+
   public boolean isDexItemBasedValueString() {
     return false;
   }
@@ -110,14 +112,30 @@
     return null;
   }
 
+  public boolean isDexValueMethodHandle() {
+    return false;
+  }
+
   public DexValueMethodHandle asDexValueMethodHandle() {
     return null;
   }
 
+  public boolean isDexValueMethodType() {
+    return false;
+  }
+
   public DexValueMethodType asDexValueMethodType() {
     return null;
   }
 
+  public boolean isDexValueAnnotation() {
+    return false;
+  }
+
+  public DexValueAnnotation asDexValueAnnotation() {
+    return null;
+  }
+
   public boolean isDexValueArray() {
     return false;
   }
@@ -158,6 +176,22 @@
     return null;
   }
 
+  public boolean isDexValueEnum() {
+    return false;
+  }
+
+  public DexValueEnum asDexValueEnum() {
+    return null;
+  }
+
+  public boolean isDexValueField() {
+    return false;
+  }
+
+  public DexValueField asDexValueField() {
+    return null;
+  }
+
   public boolean isDexValueFloat() {
     return false;
   }
@@ -182,6 +216,14 @@
     return null;
   }
 
+  public boolean isDexValueMethod() {
+    return false;
+  }
+
+  public DexValueMethod asDexValueMethod() {
+    return null;
+  }
+
   public boolean isDexValueNull() {
     return false;
   }
@@ -392,6 +434,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.BYTE;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.byteType;
     }
@@ -470,6 +517,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.SHORT;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.shortType;
     }
@@ -547,6 +599,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.CHAR;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.charType;
     }
@@ -628,6 +685,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.INT;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.intType;
     }
@@ -705,6 +767,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.LONG;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.longType;
     }
@@ -782,6 +849,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.FLOAT;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.floatType;
     }
@@ -836,8 +908,8 @@
       if (other == this) {
         return true;
       }
-      return (other instanceof DexValueFloat) &&
-          (Float.compare(value, ((DexValueFloat) other).value) == 0);
+      return other instanceof DexValueFloat
+          && Float.compare(value, ((DexValueFloat) other).value) == 0;
     }
 
     @Override
@@ -865,6 +937,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.DOUBLE;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.doubleType;
     }
@@ -937,8 +1014,6 @@
       this.value = value;
     }
 
-    protected abstract DexValueKind getValueKind();
-
     @Override
     public DexType getType(DexItemFactory factory) {
       throw new Unreachable();
@@ -1024,7 +1099,7 @@
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.STRING;
     }
 
@@ -1082,7 +1157,7 @@
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.STRING;
     }
 
@@ -1121,7 +1196,7 @@
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.TYPE;
     }
 
@@ -1149,7 +1224,7 @@
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.FIELD;
     }
 
@@ -1158,6 +1233,16 @@
         IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
       value.collectIndexedItems(indexedItems, method, instructionOffset);
     }
+
+    @Override
+    public boolean isDexValueField() {
+      return true;
+    }
+
+    @Override
+    public DexValueField asDexValueField() {
+      return this;
+    }
   }
 
   static public class DexValueMethod extends NestedDexValue<DexMethod> {
@@ -1167,7 +1252,7 @@
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.METHOD;
     }
 
@@ -1176,6 +1261,16 @@
         IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
       value.collectIndexedItems(indexedItems, method, instructionOffset);
     }
+
+    @Override
+    public boolean isDexValueMethod() {
+      return true;
+    }
+
+    @Override
+    public DexValueMethod asDexValueMethod() {
+      return this;
+    }
   }
 
   static public class DexValueEnum extends NestedDexValue<DexField> {
@@ -1185,7 +1280,7 @@
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.ENUM;
     }
 
@@ -1194,6 +1289,16 @@
         IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
       value.collectIndexedItems(indexedItems, method, instructionOffset);
     }
+
+    @Override
+    public boolean isDexValueEnum() {
+      return true;
+    }
+
+    @Override
+    public DexValueEnum asDexValueEnum() {
+      return this;
+    }
   }
 
   static public class DexValueMethodType extends NestedDexValue<DexProto> {
@@ -1203,12 +1308,17 @@
     }
 
     @Override
+    public boolean isDexValueMethodType() {
+      return true;
+    }
+
+    @Override
     public DexValueMethodType asDexValueMethodType() {
       return this;
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.METHOD_TYPE;
     }
 
@@ -1232,6 +1342,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.ARRAY;
+    }
+
+    @Override
     public void collectIndexedItems(IndexedItemCollection indexedItems,
         DexMethod method, int instructionOffset) {
       collectAll(indexedItems, values);
@@ -1310,6 +1425,21 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.ANNOTATION;
+    }
+
+    @Override
+    public boolean isDexValueAnnotation() {
+      return true;
+    }
+
+    @Override
+    public DexValueAnnotation asDexValueAnnotation() {
+      return this;
+    }
+
+    @Override
     public void collectIndexedItems(IndexedItemCollection indexedItems,
         DexMethod method, int instructionOffset) {
       value.collectIndexedItems(indexedItems, method, instructionOffset);
@@ -1377,6 +1507,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.NULL;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       throw new Unreachable();
     }
@@ -1421,7 +1556,7 @@
       if (other == this) {
         return true;
       }
-      return (other instanceof DexValueNull);
+      return other instanceof DexValueNull;
     }
 
     @Override
@@ -1458,6 +1593,11 @@
     }
 
     @Override
+    public DexValueKind getValueKind() {
+      return DexValueKind.BOOLEAN;
+    }
+
+    @Override
     public DexType getType(DexItemFactory factory) {
       return factory.booleanType;
     }
@@ -1502,7 +1642,7 @@
       if (other == this) {
         return true;
       }
-      return (other instanceof DexValueBoolean) && ((DexValueBoolean) other).value == value;
+      return other instanceof DexValueBoolean && ((DexValueBoolean) other).value == value;
     }
 
     @Override
@@ -1524,12 +1664,17 @@
     }
 
     @Override
+    public boolean isDexValueMethodHandle() {
+      return true;
+    }
+
+    @Override
     public DexValueMethodHandle asDexValueMethodHandle() {
       return this;
     }
 
     @Override
-    protected DexValueKind getValueKind() {
+    public DexValueKind getValueKind() {
       return DexValueKind.METHOD_HANDLE;
     }
 
diff --git a/src/main/java/com/android/tools/r8/graph/UseRegistry.java b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
index 2c27763..1e89e13 100644
--- a/src/main/java/com/android/tools/r8/graph/UseRegistry.java
+++ b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
@@ -3,14 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.graph;
 
-import com.android.tools.r8.graph.DexValue.DexValueDouble;
-import com.android.tools.r8.graph.DexValue.DexValueFloat;
-import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueLong;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.graph.DexValue.DexValueType;
 
 public abstract class UseRegistry {
 
@@ -128,22 +120,27 @@
     // Register bootstrap method arguments.
     // Only Type, MethodHandle, and MethodType need to be registered.
     for (DexValue arg : callSite.bootstrapArgs) {
-      if (arg instanceof DexValueType) {
-        registerTypeReference(((DexValueType) arg).value);
-      } else if (arg instanceof DexValueMethodHandle) {
-        DexMethodHandle handle = ((DexValueMethodHandle) arg).value;
-        MethodHandleUse use = isLambdaMetaFactory
-            ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
-            : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
-        registerMethodHandle(handle, use);
-      } else if (arg instanceof DexValueMethodType) {
-        registerProto(((DexValueMethodType) arg).value);
-      } else {
-        assert (arg instanceof DexValueInt)
-            || (arg instanceof DexValueLong)
-            || (arg instanceof DexValueFloat)
-            || (arg instanceof DexValueDouble)
-            || (arg instanceof DexValueString);
+      switch (arg.getValueKind()) {
+        case METHOD_HANDLE:
+          DexMethodHandle handle = arg.asDexValueMethodHandle().value;
+          MethodHandleUse use =
+              isLambdaMetaFactory
+                  ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
+                  : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+          registerMethodHandle(handle, use);
+          break;
+        case METHOD_TYPE:
+          registerProto(arg.asDexValueMethodType().value);
+          break;
+        case TYPE:
+          registerTypeReference(arg.asDexValueType().value);
+          break;
+        default:
+          assert arg.isDexValueInt()
+              || arg.isDexValueLong()
+              || arg.isDexValueFloat()
+              || arg.isDexValueDouble()
+              || arg.isDexValueString();
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 06c4bdf..6f1ff03d 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -568,16 +568,22 @@
     for (int i = 0; i < bootstrapArgs.size(); i++) {
       DexValue argument = bootstrapArgs.get(i);
       DexValue newArgument = null;
-      if (argument instanceof DexValueMethodHandle) {
-        newArgument = rewriteDexValueMethodHandle(argument.asDexValueMethodHandle(), method, use);
-      } else if (argument instanceof DexValueMethodType) {
-        newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
-      } else if (argument instanceof DexValueType) {
-        DexType oldType = ((DexValueType) argument).value;
-        DexType newType = appView.graphLense().lookupType(oldType);
-        if (newType != oldType) {
-          newArgument = new DexValueType(newType);
-        }
+      switch (argument.getValueKind()) {
+        case METHOD_HANDLE:
+          newArgument = rewriteDexValueMethodHandle(argument.asDexValueMethodHandle(), method, use);
+          break;
+        case METHOD_TYPE:
+          newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
+          break;
+        case TYPE:
+          DexType oldType = argument.asDexValueType().value;
+          DexType newType = appView.graphLense().lookupType(oldType);
+          if (newType != oldType) {
+            newArgument = new DexValueType(newType);
+          }
+          break;
+        default:
+          // Intentionally empty.
       }
       if (newArgument != null) {
         if (newBootstrapArgs == null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
index 3cadabf..efd6f7d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
@@ -16,6 +16,9 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
+import com.android.tools.r8.graph.DexValue.DexValueArray;
+import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.code.Invoke;
 import com.android.tools.r8.ir.conversion.IRConverter;
@@ -201,22 +204,22 @@
       String name = element.name.toString();
       if (annotation.type == factory.annotationCovariantReturnType) {
         if (name.equals("returnType")) {
-          if (!(element.value instanceof DexValue.DexValueType)) {
+          DexValueType dexValueType = element.value.asDexValueType();
+          if (dexValueType == null) {
             throw new CompilationError(
                 String.format(
                     "Expected element \"returnType\" of CovariantReturnType annotation to "
                         + "reference a type (method: \"%s\", was: %s)",
                     method.toSourceString(), element.value.getClass().getCanonicalName()));
           }
-
-          DexValue.DexValueType dexValueType = (DexValue.DexValueType) element.value;
           covariantReturnTypes.add(dexValueType.value);
         } else if (name.equals("presentAfter")) {
           hasPresentAfterElement = true;
         }
       } else {
         if (name.equals("value")) {
-          if (!(element.value instanceof DexValue.DexValueArray)) {
+          DexValueArray array = element.value.asDexValueArray();
+          if (array == null) {
             throw new CompilationError(
                 String.format(
                     "Expected element \"value\" of CovariantReturnTypes annotation to "
@@ -224,11 +227,10 @@
                     method.toSourceString(), element.value.getClass().getCanonicalName()));
           }
 
-          DexValue.DexValueArray array = (DexValue.DexValueArray) element.value;
           // Handle the inner dalvik.annotation.codegen.CovariantReturnType annotations recursively.
           for (DexValue value : array.getValues()) {
-            assert value instanceof DexValue.DexValueAnnotation;
-            DexValue.DexValueAnnotation innerAnnotation = (DexValue.DexValueAnnotation) value;
+            assert value.isDexValueAnnotation();
+            DexValueAnnotation innerAnnotation = value.asDexValueAnnotation();
             getCovariantReturnTypesFromAnnotation(
                 clazz, method, innerAnnotation.value, covariantReturnTypes);
           }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 403f2f0..1a4c416 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -196,9 +196,9 @@
           DexCallSite callSite = instruction.asInvokeCustom().getCallSite();
           reportStaticInterfaceMethodHandle(encodedMethod.method, callSite.bootstrapMethod);
           for (DexValue arg : callSite.bootstrapArgs) {
-            if (arg instanceof DexValue.DexValueMethodHandle) {
-              reportStaticInterfaceMethodHandle(encodedMethod.method,
-                  ((DexValue.DexValueMethodHandle) arg).value);
+            if (arg.isDexValueMethodHandle()) {
+              reportStaticInterfaceMethodHandle(
+                  encodedMethod.method, arg.asDexValueMethodHandle().value);
             }
           }
           continue;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index 834a492..d58d6b6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -212,11 +213,11 @@
     }
 
     // Extract recipe.
-    DexValue recipeValue = bootstrapArgs.get(0);
-    if (!(recipeValue instanceof DexValue.DexValueString)) {
+    DexValueString recipeValue = bootstrapArgs.get(0).asDexValueString();
+    if (recipeValue == null) {
       throw error(method, "bootstrap method argument `recipe` must be a string");
     }
-    String recipe = ((DexValue.DexValueString) recipeValue).getValue().toString();
+    String recipe = recipeValue.getValue().toString();
 
     // Collect chunks and patch the instruction.
     ConcatBuilder builder = new ConcatBuilder(appView, code, blocks, instructions);
@@ -273,8 +274,8 @@
   }
 
   private static String convertToString(DexMethod method, DexValue value) {
-    if (value instanceof DexValue.DexValueString) {
-      return ((DexValue.DexValueString) value).getValue().toString();
+    if (value.isDexValueString()) {
+      return value.asDexValueString().getValue().toString();
     }
     throw error(method,
         "const arg referenced from `recipe` is not supported: " + value.getClass().getName());
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
index 7422bc0..9dce489 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
@@ -17,12 +17,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueField;
-import com.android.tools.r8.graph.DexValue.DexValueMethod;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -49,30 +43,29 @@
   }
 
   private void accept(DexValue value) {
-    if (value instanceof DexValueType) {
-      accept(((DexValueType) value).value);
-      return;
-    }
-    if (value instanceof DexValueArray) {
-      for (DexValue subValue : ((DexValueArray) value).getValues()) {
-        accept(subValue);
-      }
-      return;
-    }
-    if (value instanceof DexValueMethod) {
-      accept(((DexValueMethod) value).value, null);
-      return;
-    }
-    if (value instanceof DexValueMethodHandle) {
-      accept(((DexValueMethodHandle) value).value);
-      return;
-    }
-    if (value instanceof DexValueMethodType) {
-      accept(((DexValueMethodType) value).value);
-      return;
-    }
-    if (value instanceof DexValueField) {
-      accept(((DexValueField) value).value, null);
+    switch (value.getValueKind()) {
+      case ARRAY:
+        for (DexValue elementValue : value.asDexValueArray().getValues()) {
+          accept(elementValue);
+        }
+        break;
+      case FIELD:
+        accept(value.asDexValueField().value, null);
+        break;
+      case METHOD:
+        accept(value.asDexValueMethod().value, null);
+        break;
+      case METHOD_HANDLE:
+        accept(value.asDexValueMethodHandle().value);
+        break;
+      case METHOD_TYPE:
+        accept(value.asDexValueMethodType().value);
+        break;
+      case TYPE:
+        accept(value.asDexValueType().value);
+        break;
+      default:
+        // Intentionally empty.
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 7822316..688d59b 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -26,13 +26,8 @@
 import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
 import com.android.tools.r8.graph.DexValue.DexValueEnum;
-import com.android.tools.r8.graph.DexValue.DexValueField;
 import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueMethod;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
 import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.InnerClassAttribute;
 import com.android.tools.r8.graph.NestMemberClassAttribute;
@@ -234,29 +229,26 @@
   }
 
   private String getSignature(DexAnnotationSet annotations) {
-    DexValueArray value =
-        (DexValueArray)
-            getSystemAnnotationValue(annotations, application.dexItemFactory.annotationSignature);
+    DexValue value =
+        getSystemAnnotationValue(annotations, application.dexItemFactory.annotationSignature);
     if (value == null) {
       return null;
     }
     // Signature has already been minified by ClassNameMinifier.renameTypesInGenericSignatures().
-    DexValue[] parts = value.getValues();
     StringBuilder res = new StringBuilder();
-    for (DexValue part : parts) {
-      res.append(((DexValueString) part).getValue().toString());
+    for (DexValue part : value.asDexValueArray().getValues()) {
+      res.append(part.asDexValueString().getValue().toString());
     }
     return res.toString();
   }
 
   private ImmutableMap<DexString, DexValue> getAnnotationDefaults(DexAnnotationSet annotations) {
-    DexValueAnnotation value =
-        (DexValueAnnotation)
-            getSystemAnnotationValue(annotations, application.dexItemFactory.annotationDefault);
+    DexValue value =
+        getSystemAnnotationValue(annotations, application.dexItemFactory.annotationDefault);
     if (value == null) {
       return ImmutableMap.of();
     }
-    DexEncodedAnnotation annotation = value.value;
+    DexEncodedAnnotation annotation = value.asDexValueAnnotation().value;
     Builder<DexString, DexValue> builder = ImmutableMap.builder();
     for (DexAnnotationElement element : annotation.elements) {
       builder.put(element.name, element.value);
@@ -265,16 +257,15 @@
   }
 
   private String[] getExceptions(DexAnnotationSet annotations) {
-    DexValueArray value =
-        (DexValueArray)
-            getSystemAnnotationValue(annotations, application.dexItemFactory.annotationThrows);
+    DexValue value =
+        getSystemAnnotationValue(annotations, application.dexItemFactory.annotationThrows);
     if (value == null) {
       return null;
     }
-    DexValue[] values = value.getValues();
+    DexValue[] values = value.asDexValueArray().getValues();
     String[] res = new String[values.length];
     for (int i = 0; i < values.length; i++) {
-      res[i] = namingLens.lookupInternalName(((DexValueType) values[i]).value);
+      res[i] = namingLens.lookupInternalName(values[i].asDexValueType().value);
     }
     return res;
   }
@@ -331,13 +322,13 @@
         assert annotation.annotation.elements.length == 2;
         assert annotation.annotation.elements[0].name.toString().equals("names");
         assert annotation.annotation.elements[1].name.toString().equals("accessFlags");
-        DexValueArray names = (DexValueArray) annotation.annotation.elements[0].value;
-        DexValueArray accessFlags = (DexValueArray) annotation.annotation.elements[1].value;
+        DexValueArray names = annotation.annotation.elements[0].value.asDexValueArray();
+        DexValueArray accessFlags = annotation.annotation.elements[1].value.asDexValueArray();
         assert names != null && accessFlags != null;
         assert names.getValues().length == accessFlags.getValues().length;
         for (int i = 0; i < names.getValues().length; i++) {
-          DexValueString name = (DexValueString) names.getValues()[i];
-          DexValueInt access = (DexValueInt) accessFlags.getValues()[i];
+          DexValueString name = names.getValues()[i].asDexValueString();
+          DexValueInt access = accessFlags.getValues()[i].asDexValueInt();
           visitor.visitParameter(name.value.toString(), access.value);
         }
       }
@@ -392,44 +383,64 @@
   }
 
   private void writeAnnotationElement(AnnotationVisitor visitor, String name, DexValue value) {
-    if (value instanceof DexValueAnnotation) {
-      DexValueAnnotation valueAnnotation = (DexValueAnnotation) value;
-      AnnotationVisitor innerVisitor =
-          visitor.visitAnnotation(
-              name, namingLens.lookupDescriptor(valueAnnotation.value.type).toString());
-      if (innerVisitor != null) {
-        writeAnnotation(innerVisitor, valueAnnotation.value);
-        innerVisitor.visitEnd();
-      }
-    } else if (value instanceof DexValueArray) {
-      DexValue[] values = ((DexValueArray) value).getValues();
-      AnnotationVisitor innerVisitor = visitor.visitArray(name);
-      if (innerVisitor != null) {
-        for (DexValue arrayValue : values) {
-          writeAnnotationElement(innerVisitor, null, arrayValue);
+    switch (value.getValueKind()) {
+      case ANNOTATION:
+        {
+          DexValueAnnotation valueAnnotation = value.asDexValueAnnotation();
+          AnnotationVisitor innerVisitor =
+              visitor.visitAnnotation(
+                  name, namingLens.lookupDescriptor(valueAnnotation.value.type).toString());
+          if (innerVisitor != null) {
+            writeAnnotation(innerVisitor, valueAnnotation.value);
+            innerVisitor.visitEnd();
+          }
         }
-        innerVisitor.visitEnd();
-      }
-    } else if (value instanceof DexValueEnum) {
-      DexValueEnum en = (DexValueEnum) value;
-      visitor.visitEnum(
-          name, namingLens.lookupDescriptor(en.value.type).toString(), en.value.name.toString());
-    } else if (value instanceof DexValueField) {
-      throw new Unreachable("writeAnnotationElement of DexValueField");
-    } else if (value instanceof DexValueMethod) {
-      throw new Unreachable("writeAnnotationElement of DexValueMethod");
-    } else if (value instanceof DexValueMethodHandle) {
-      throw new Unreachable("writeAnnotationElement of DexValueMethodHandle");
-    } else if (value instanceof DexValueMethodType) {
-      throw new Unreachable("writeAnnotationElement of DexValueMethodType");
-    } else if (value instanceof DexValueString) {
-      DexValueString str = (DexValueString) value;
-      visitor.visit(name, str.getValue().toString());
-    } else if (value instanceof DexValueType) {
-      DexValueType ty = (DexValueType) value;
-      visitor.visit(name, Type.getType(namingLens.lookupDescriptor(ty.value).toString()));
-    } else {
-      visitor.visit(name, value.getBoxedValue());
+        break;
+
+      case ARRAY:
+        {
+          DexValue[] values = value.asDexValueArray().getValues();
+          AnnotationVisitor innerVisitor = visitor.visitArray(name);
+          if (innerVisitor != null) {
+            for (DexValue elementValue : values) {
+              writeAnnotationElement(innerVisitor, null, elementValue);
+            }
+            innerVisitor.visitEnd();
+          }
+        }
+        break;
+
+      case ENUM:
+        DexValueEnum en = value.asDexValueEnum();
+        visitor.visitEnum(
+            name, namingLens.lookupDescriptor(en.value.type).toString(), en.value.name.toString());
+        break;
+
+      case FIELD:
+        throw new Unreachable("writeAnnotationElement of DexValueField");
+
+      case METHOD:
+        throw new Unreachable("writeAnnotationElement of DexValueMethod");
+
+      case METHOD_HANDLE:
+        throw new Unreachable("writeAnnotationElement of DexValueMethodHandle");
+
+      case METHOD_TYPE:
+        throw new Unreachable("writeAnnotationElement of DexValueMethodType");
+
+      case STRING:
+        visitor.visit(name, value.asDexValueString().getValue().toString());
+        break;
+
+      case TYPE:
+        visitor.visit(
+            name,
+            Type.getType(namingLens.lookupDescriptor(value.asDexValueType().value).toString()));
+        break;
+
+      default:
+        visitor.visit(name, value.getBoxedValue());
+        break;
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index fec6a34..5a3e469 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -11,7 +11,6 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.utils.StringDiagnostic;
 import java.util.IdentityHashMap;
 import java.util.Map;
@@ -96,10 +95,10 @@
   }
 
   private static int[] getUnboxedIntArray(DexValue v, String elementName) {
-    if (!(v instanceof DexValueArray)) {
+    if (!v.isDexValueArray()) {
       throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
     }
-    DexValueArray intArrayValue = (DexValueArray) v;
+    DexValueArray intArrayValue = v.asDexValueArray();
     DexValue[] values = intArrayValue.getValues();
     int[] result = new int [values.length];
     for (int i = 0; i < values.length; i++) {
@@ -109,10 +108,10 @@
   }
 
   private static String[] getUnboxedStringArray(DexValue v, String elementName) {
-    if (!(v instanceof DexValueArray)) {
+    if (!v.isDexValueArray()) {
       throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
     }
-    DexValueArray stringArrayValue = (DexValueArray) v;
+    DexValueArray stringArrayValue = v.asDexValueArray();
     DexValue[] values = stringArrayValue.getValues();
     String[] result = new String [values.length];
     for (int i = 0; i < values.length; i++) {
@@ -122,10 +121,10 @@
   }
 
   private static String getUnboxedString(DexValue v, String elementName) {
-    if (!(v instanceof DexValueString)) {
+    if (!v.isDexValueString()) {
       throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
     }
-    return ((DexValueString) v).getValue().toString();
+    return v.asDexValueString().getValue().toString();
   }
 
   private static class MetadataError extends RuntimeException {
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
index 72d5558..a0b1328 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
@@ -69,8 +69,8 @@
   private void adaptClassStringsInStaticField(DexEncodedField encodedField) {
     assert encodedField.accessFlags.isStatic();
     DexValue staticValue = encodedField.getStaticValue();
-    if (staticValue instanceof DexValueString) {
-      DexString original = ((DexValueString) staticValue).getValue();
+    if (staticValue.isDexValueString()) {
+      DexString original = staticValue.asDexValueString().getValue();
       encodedField.setStaticValue(new DexValueString(getRenamedStringLiteral(original)));
     }
   }
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
index 47d6431..eb799b5 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
@@ -18,7 +18,6 @@
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexItemBasedValueString;
 import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.ir.code.BasicBlock;
@@ -81,11 +80,11 @@
     if (!identifierNameStrings.containsKey(encodedField.field)) {
       return;
     }
-    DexValue staticValue = encodedField.getStaticValue();
-    if (!(staticValue instanceof DexValueString)) {
+    DexValueString staticValue = encodedField.getStaticValue().asDexValueString();
+    if (staticValue == null) {
       return;
     }
-    DexString original = ((DexValueString) staticValue).getValue();
+    DexString original = staticValue.getValue();
     DexReference itemBasedString = inferMemberOrTypeFromNameString(appView, original);
     if (itemBasedString != null) {
       encodedField.setStaticValue(
diff --git a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
index a6fd390..08a4ae9 100644
--- a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
+++ b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
@@ -10,7 +10,6 @@
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexAnnotationElement;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.AndroidAppConsumers;
@@ -30,7 +29,6 @@
 import org.junit.rules.TemporaryFolder;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Opcodes;
 
 public class JSR45Tests {
 
@@ -158,10 +156,10 @@
     Assert.assertNotNull(annotationElement);
     Assert.assertTrue(annotationElement.length == 1);
     Assert.assertEquals("value", annotationElement[0].name.toString());
-    Assert.assertTrue(annotationElement[0].value instanceof DexValueString);
+    Assert.assertTrue(annotationElement[0].value.isDexValueString());
     Assert.assertEquals(
         sourceDebugExtensionReader.debugSourceExtension,
-        ((DexValueString) annotationElement[0].value).value.toSourceString());
+        annotationElement[0].value.asDexValueString().value.toSourceString());
   }
 
   private String getGeneratedProguardMap() throws IOException {
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
index 1c7c5bc..627a059 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -284,19 +283,22 @@
   private static int countRenamedClassIdentifier(
       CodeInspector inspector, List<DexEncodedField> fields) {
     return fields.stream()
-        .filter(encodedField -> encodedField.getStaticValue() instanceof DexValueString)
-        .reduce(0, (cnt, encodedField) -> {
-          String cnstString =
-              ((DexValueString) encodedField.getStaticValue()).getValue().toString();
-          if (isValidJavaType(cnstString)) {
-            ClassSubject classSubject = inspector.clazz(cnstString);
-            if (classSubject.isRenamed()
-                && descriptorToJavaType(classSubject.getFinalDescriptor()).equals(cnstString)) {
-              return cnt + 1;
-            }
-          }
-          return cnt;
-        }, Integer::sum);
+        .filter(encodedField -> encodedField.getStaticValue().isDexValueString())
+        .reduce(
+            0,
+            (cnt, encodedField) -> {
+              String cnstString =
+                  encodedField.getStaticValue().asDexValueString().getValue().toString();
+              if (isValidJavaType(cnstString)) {
+                ClassSubject classSubject = inspector.clazz(cnstString);
+                if (classSubject.isRenamed()
+                    && descriptorToJavaType(classSubject.getFinalDescriptor()).equals(cnstString)) {
+                  return cnt + 1;
+                }
+              }
+              return cnt;
+            },
+            Integer::sum);
   }
 
   private static Set<InstructionSubject> getRenamedMemberIdentifierConstStrings(
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
index e9ce1d8..116ce4a 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
@@ -26,7 +26,6 @@
 import com.android.tools.r8.code.SputObject;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.smali.SmaliBuilder;
 import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
 import com.android.tools.r8.smali.SmaliTestBase;
@@ -278,8 +277,8 @@
     assertTrue(clazz.isPresent());
     FieldSubject field = clazz.field("java.lang.String", "sClassName");
     assertTrue(field.isPresent());
-    assertTrue(field.getStaticValue() instanceof DexValueString);
-    String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+    assertTrue(field.getStaticValue().isDexValueString());
+    String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
     assertEquals(BOO, defaultValue);
   }
 
@@ -300,8 +299,8 @@
     assertTrue(clazz.isPresent());
     FieldSubject field = clazz.field("java.lang.String", "sClassName");
     assertTrue(field.isPresent());
-    assertTrue(field.getStaticValue() instanceof DexValueString);
-    String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+    assertTrue(field.getStaticValue().isDexValueString());
+    String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
     assertNotEquals(BOO, defaultValue);
   }
 
@@ -324,8 +323,8 @@
     assertTrue(clazz.isPresent());
     FieldSubject field = clazz.field("java.lang.String", "sFieldName");
     assertTrue(field.isPresent());
-    assertTrue(field.getStaticValue() instanceof DexValueString);
-    String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+    assertTrue(field.getStaticValue().isDexValueString());
+    String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
     assertNotEquals(fooInBoo, defaultValue);
   }
 
@@ -348,8 +347,8 @@
     assertTrue(clazz.isPresent());
     FieldSubject field = clazz.field("java.lang.String", "sMethodName");
     assertTrue(field.isPresent());
-    assertTrue(field.getStaticValue() instanceof DexValueString);
-    String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+    assertTrue(field.getStaticValue().isDexValueString());
+    String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
     assertNotEquals(fooInBoo, defaultValue);
   }
 
diff --git a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
index 1dabc11..e1cd05a 100644
--- a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
+++ b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.graph.DexAnnotationElement;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.StringUtils;
@@ -47,12 +46,12 @@
     DexAnnotationElement[] elements = signature.getAnnotation().elements;
     assertEquals(1, elements.length);
     assertEquals("value", elements[0].name.toString());
-    assertTrue(elements[0].value instanceof DexValueArray);
-    DexValueArray array = (DexValueArray) elements[0].value;
+    assertTrue(elements[0].value.isDexValueArray());
+    DexValueArray array = elements[0].value.asDexValueArray();
     StringBuilder builder = new StringBuilder();
     for (DexValue value : array.getValues()) {
-      assertTrue(value instanceof DexValueString);
-      builder.append(((DexValueString) value).value);
+      assertTrue(value.isDexValueString());
+      builder.append(value.asDexValueString().value);
     }
     String fooImplFinalDescriptor =
         DescriptorUtils.javaTypeToDescriptor(inspector.clazz(FooImpl.class).getFinalName());
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
index f0270f1..662b22e 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
@@ -13,15 +13,6 @@
 import com.android.tools.r8.code.SgetBoolean;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueBoolean;
-import com.android.tools.r8.graph.DexValue.DexValueByte;
-import com.android.tools.r8.graph.DexValue.DexValueChar;
-import com.android.tools.r8.graph.DexValue.DexValueDouble;
-import com.android.tools.r8.graph.DexValue.DexValueFloat;
-import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueLong;
-import com.android.tools.r8.graph.DexValue.DexValueShort;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.smali.SmaliBuilder;
 import com.android.tools.r8.smali.SmaliTestBase;
 import com.android.tools.r8.utils.AndroidApp;
@@ -102,48 +93,49 @@
     DexValue value;
     assertTrue(inspector.clazz("Test").field("boolean", "booleanField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("boolean", "booleanField").getStaticValue();
-    assertTrue(value instanceof DexValueBoolean);
-    assertTrue(((DexValueBoolean) value).getValue());
+    assertTrue(value.isDexValueBoolean());
+    assertTrue(value.asDexValueBoolean().getValue());
 
     assertTrue(inspector.clazz("Test").field("byte", "byteField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("byte", "byteField").getStaticValue();
-    assertTrue(value instanceof DexValueByte);
-    assertEquals(1, ((DexValueByte) value).getValue());
+    assertTrue(value.isDexValueByte());
+    assertEquals(1, value.asDexValueByte().getValue());
 
     assertTrue(inspector.clazz("Test").field("short", "shortField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("short", "shortField").getStaticValue();
-    assertTrue(value instanceof DexValueShort);
-    assertEquals(2, ((DexValueShort) value).getValue());
+    assertTrue(value.isDexValueShort());
+    assertEquals(2, value.asDexValueShort().getValue());
 
     assertTrue(inspector.clazz("Test").field("int", "intField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("int", "intField").getStaticValue();
-    assertTrue(value instanceof DexValueInt);
-    assertEquals(3, ((DexValueInt) value).getValue());
+    assertTrue(value.isDexValueInt());
+    assertEquals(3, value.asDexValueInt().getValue());
 
     assertTrue(inspector.clazz("Test").field("long", "longField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("long", "longField").getStaticValue();
-    assertTrue(value instanceof DexValueLong);
-    assertEquals(4, ((DexValueLong) value).getValue());
+    assertTrue(value.isDexValueLong());
+    assertEquals(4, value.asDexValueLong().getValue());
 
     assertTrue(inspector.clazz("Test").field("float", "floatField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("float", "floatField").getStaticValue();
-    assertTrue(value instanceof DexValueFloat);
-    assertEquals(5.0f, ((DexValueFloat) value).getValue(), 0.0);
+    assertTrue(value.isDexValueFloat());
+    assertEquals(5.0f, value.asDexValueFloat().getValue(), 0.0);
 
     assertTrue(inspector.clazz("Test").field("double", "doubleField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("double", "doubleField").getStaticValue();
-    assertTrue(value instanceof DexValueDouble);
-    assertEquals(6.0f, ((DexValueDouble) value).getValue(), 0.0);
+    assertTrue(value.isDexValueDouble());
+    assertEquals(6.0f, value.asDexValueDouble().getValue(), 0.0);
 
     assertTrue(inspector.clazz("Test").field("char", "charField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("char", "charField").getStaticValue();
-    assertTrue(value instanceof DexValueChar);
-    assertEquals(0x30 + 7, ((DexValueChar) value).getValue());
+    assertTrue(value.isDexValueChar());
+    assertEquals(0x30 + 7, value.asDexValueChar().getValue());
 
-    assertTrue(inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
+    assertTrue(
+        inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("java.lang.String", "stringField").getStaticValue();
-    assertTrue(value instanceof DexValueString);
-    assertEquals(("8"), ((DexValueString) value).getValue().toString());
+    assertTrue(value.isDexValueString());
+    assertEquals(("8"), value.asDexValueString().getValue().toString());
 
     String result = runArt(processedApplication);
 
@@ -319,13 +311,14 @@
     DexValue value;
     assertTrue(inspector.clazz("Test").field("int", "intField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("int", "intField").getStaticValue();
-    assertTrue(value instanceof DexValueInt);
-    assertEquals(3, ((DexValueInt) value).getValue());
+    assertTrue(value.isDexValueInt());
+    assertEquals(3, value.asDexValueInt().getValue());
 
-    assertTrue(inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
+    assertTrue(
+        inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("java.lang.String", "stringField").getStaticValue();
-    assertTrue(value instanceof DexValueString);
-    assertEquals(("7"), ((DexValueString) value).getValue().toString());
+    assertTrue(value.isDexValueString());
+    assertEquals(("7"), value.asDexValueString().getValue().toString());
 
     String result = runArt(processedApplication);
 
@@ -389,14 +382,15 @@
 
     assertTrue(inspector.clazz("Test").field("int", "intField").hasExplicitStaticValue());
     DexValue value = inspector.clazz("Test").field("int", "intField").getStaticValue();
-    assertTrue(value instanceof DexValueInt);
-    assertEquals(1, ((DexValueInt) value).getValue());
+    assertTrue(value.isDexValueInt());
+    assertEquals(1, value.asDexValueInt().getValue());
 
-    assertTrue(inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
+    assertTrue(
+        inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
     value = inspector.clazz("Test").field("java.lang.String", "stringField").getStaticValue();
-    assertTrue(value instanceof DexValueString);
+    assertTrue(value.isDexValueString());
     // We stop at control-flow and therefore the initial value for the string field will be 5.
-    assertEquals(("5"), ((DexValueString) value).getValue().toString());
+    assertEquals(("5"), value.asDexValueString().getValue().toString());
 
     DexCode code = inspector.clazz("Test").clinit().getMethod().getCode().asDexCode();
     assertTrue(code.instructions[0] instanceof SgetBoolean);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 63c85d5..1f25605 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -26,7 +26,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.ClassNamingForNameMapper;
@@ -228,13 +227,12 @@
     }
     assert annotation.annotation.elements.length == 1;
     DexAnnotationElement element = annotation.annotation.elements[0];
-    assert element.value instanceof DexValueArray;
+    assert element.value.isDexValueArray();
     StringBuilder builder = new StringBuilder();
-    DexValueArray valueArray = (DexValueArray) element.value;
+    DexValueArray valueArray = element.value.asDexValueArray();
     for (DexValue value : valueArray.getValues()) {
-      assertTrue(value instanceof DexValueString);
-      DexValueString s = (DexValueString) value;
-      builder.append(s.getValue());
+      assertTrue(value.isDexValueString());
+      builder.append(value.asDexValueString().getValue());
     }
     return builder.toString();
   }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java
index b3a0143..73972f4 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.kotlin.Kotlin;
 import java.util.IdentityHashMap;
 import java.util.Map;
@@ -51,10 +50,10 @@
   }
 
   private static int[] getUnboxedIntArray(DexValue v, String elementName) {
-    if (!(v instanceof DexValueArray)) {
+    if (!v.isDexValueArray()) {
       throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
     }
-    DexValueArray intArrayValue = (DexValueArray) v;
+    DexValueArray intArrayValue = v.asDexValueArray();
     DexValue[] values = intArrayValue.getValues();
     int[] result = new int [values.length];
     for (int i = 0; i < values.length; i++) {
@@ -64,10 +63,10 @@
   }
 
   private static String[] getUnboxedStringArray(DexValue v, String elementName) {
-    if (!(v instanceof DexValueArray)) {
+    if (!v.isDexValueArray()) {
       throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
     }
-    DexValueArray stringArrayValue = (DexValueArray) v;
+    DexValueArray stringArrayValue = v.asDexValueArray();
     DexValue[] values = stringArrayValue.getValues();
     String[] result = new String [values.length];
     for (int i = 0; i < values.length; i++) {
@@ -77,10 +76,10 @@
   }
 
   private static String getUnboxedString(DexValue v, String elementName) {
-    if (!(v instanceof DexValueString)) {
+    if (!v.isDexValueString()) {
       throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
     }
-    return ((DexValueString) v).getValue().toString();
+    return v.asDexValueString().getValue().toString();
   }
 
   private static class MetadataError extends RuntimeException {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java
index a5cca23..e2561b0 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java
@@ -6,7 +6,7 @@
 
 import com.android.tools.r8.graph.DexAnnotationElement;
 import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.graph.DexValue.DexValueArray;
 import com.android.tools.r8.naming.MemberNaming.Signature;
 
 public abstract class MemberSubject extends Subject {
@@ -66,12 +66,12 @@
     assert annotation.getAnnotation().elements.length == 1;
     DexAnnotationElement element = annotation.getAnnotation().elements[0];
     assert element.name.toString().equals("value");
-    assert element.value instanceof DexValue.DexValueArray;
-    DexValue.DexValueArray array = (DexValue.DexValueArray) element.value;
+    assert element.value.isDexValueArray();
+    DexValueArray array = element.value.asDexValueArray();
     StringBuilder builder = new StringBuilder();
     for (DexValue value : array.getValues()) {
-      if (value instanceof DexValueString) {
-        builder.append(((DexValueString) value).value);
+      if (value.isDexValueString()) {
+        builder.append(value.asDexValueString().value);
       } else {
         builder.append(value.toString());
       }