Merge commit '819b3dfe0b79a426565aeb717d91d2a83d64cb72' into dev-release
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index e46d5c1..85abb47 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -21,7 +21,6 @@
 import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
 import com.android.tools.r8.ir.optimize.AssertionsRewriter;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
-import com.android.tools.r8.ir.optimize.library.LibraryOptimizationInfoInitializer;
 import com.android.tools.r8.naming.PrefixRewritingNamingLens;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.utils.AndroidApp;
@@ -180,8 +179,6 @@
 
       AppView<?> appView = AppView.createForD8(appInfo, options, rewritePrefix);
 
-      new LibraryOptimizationInfoInitializer(appView).run();
-
       IRConverter converter = new IRConverter(appView, timing, printer);
       app = converter.convert(app, executor);
 
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 5e47207..a647cf5 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -52,6 +52,8 @@
           AppView.createForR8(new AppInfoWithSubtyping(application), options);
       appView.setAppServices(AppServices.builder(appView).build());
 
+      MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
+
       RootSet mainDexRootSet =
           new RootSetBuilder(appView, application, options.mainDexKeepRules).run(executor);
 
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index d8d93ab..d492e67 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -250,7 +250,7 @@
       for (DexType type : method.method.proto.parameters.values) {
         registerTypeReference(type);
       }
-      for (DexAnnotation annotation : method.annotations.annotations) {
+      for (DexAnnotation annotation : method.annotations().annotations) {
         if (annotation.annotation.type == appInfo.dexItemFactory().annotationThrows) {
           DexValueArray dexValues = (DexValueArray) annotation.annotation.elements[0].value;
           for (DexValue dexValType : dexValues.getValues()) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 78471d6..7db3d7c 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -31,6 +31,7 @@
 import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis;
 import com.android.tools.r8.ir.analysis.proto.GeneratedExtensionRegistryShrinker;
 import com.android.tools.r8.ir.conversion.IRConverter;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
 import com.android.tools.r8.ir.desugar.NestedPrivateMethodLense;
 import com.android.tools.r8.ir.desugar.R8NestBasedAccessDesugaring;
 import com.android.tools.r8.ir.optimize.AssertionsRewriter;
@@ -43,7 +44,6 @@
 import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector;
 import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector.UnusedArgumentsGraphLense;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
-import com.android.tools.r8.ir.optimize.library.LibraryOptimizationInfoInitializer;
 import com.android.tools.r8.jar.CfApplicationWriter;
 import com.android.tools.r8.kotlin.Kotlin;
 import com.android.tools.r8.kotlin.KotlinInfo;
@@ -270,6 +270,14 @@
           AppView.createForR8(new AppInfoWithSubtyping(application), options);
       appView.setAppServices(AppServices.builder(appView).build());
 
+      // Up-front check for valid library setup.
+      if (!options.mainDexKeepRules.isEmpty()) {
+        MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
+      }
+      if (!options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
+        BackportedMethodRewriter.checkForAssumedLibraryTypes(appView);
+      }
+
       List<ProguardConfigurationRule> synthesizedProguardRules = new ArrayList<>();
       timing.begin("Strip unused code");
       Set<DexType> classesToRetainInnerClassAttributeFor = null;
@@ -328,8 +336,6 @@
 
         appView.rootSet().checkAllRulesAreUsed(options);
 
-        new LibraryOptimizationInfoInitializer(appView).run();
-
         if (options.proguardSeedsConsumer != null) {
           ByteArrayOutputStream bytes = new ByteArrayOutputStream();
           PrintStream out = new PrintStream(bytes);
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java
index 21e4f10..efeccec 100644
--- a/src/main/java/com/android/tools/r8/ResourceShrinker.java
+++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -54,7 +54,6 @@
 import com.google.common.collect.Sets;
 import com.google.common.collect.Streams;
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -232,36 +231,24 @@
     }
 
     private void processAnnotations(DexProgramClass classDef) {
-      Stream<DexAnnotation> instanceFieldAnnotations =
-          classDef.instanceFields().stream()
+      Stream<DexAnnotation> classAnnotations = classDef.annotations().stream();
+      Stream<DexAnnotation> fieldAnnotations =
+          Streams.stream(classDef.fields())
               .filter(DexEncodedField::hasAnnotation)
-              .flatMap(f -> Arrays.stream(f.annotations.annotations));
-      Stream<DexAnnotation> staticFieldAnnotations =
-          classDef.staticFields().stream()
-              .filter(DexEncodedField::hasAnnotation)
-              .flatMap(f -> Arrays.stream(f.annotations.annotations));
-      Stream<DexAnnotation> virtualMethodAnnotations =
-          classDef.virtualMethods().stream()
+              .flatMap(f -> f.annotations().stream());
+      Stream<DexAnnotation> methodAnnotations =
+          Streams.stream(classDef.methods())
               .filter(DexEncodedMethod::hasAnnotation)
-              .flatMap(m -> Arrays.stream(m.annotations.annotations));
-      Stream<DexAnnotation> directMethodAnnotations =
-          classDef.directMethods().stream()
-              .filter(DexEncodedMethod::hasAnnotation)
-              .flatMap(m -> Arrays.stream(m.annotations.annotations));
-      Stream<DexAnnotation> classAnnotations = Arrays.stream(classDef.annotations.annotations);
+              .flatMap(m -> m.annotations().stream());
 
-      Streams.concat(
-          instanceFieldAnnotations,
-          staticFieldAnnotations,
-          virtualMethodAnnotations,
-          directMethodAnnotations,
-          classAnnotations)
-          .forEach(annotation -> {
-            for (DexAnnotationElement element : annotation.annotation.elements) {
-              DexValue value = element.value;
-              processAnnotationValue(value);
-            }
-          });
+      Streams.concat(classAnnotations, fieldAnnotations, methodAnnotations)
+          .forEach(
+              annotation -> {
+                for (DexAnnotationElement element : annotation.annotation.elements) {
+                  DexValue value = element.value;
+                  processAnnotationValue(value);
+                }
+              });
     }
 
     private void processIntArrayPayload(Instruction instruction) {
diff --git a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
index 94633a0..93ee213 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -57,6 +57,7 @@
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.StringUtils.BraceType;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import it.unimi.dsi.fastutil.objects.Reference2IntMap;
 import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
 import java.util.ArrayList;
@@ -64,6 +65,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -224,8 +226,42 @@
     return "options.itemFactory.createString(" + quote(string.toString()) + ")";
   }
 
+  private final Map<String, String> knownTypeFields =
+      ImmutableMap.<String, String>builder()
+          .put("Z", "booleanType")
+          .put("B", "byteType")
+          .put("C", "charType")
+          .put("D", "doubleType")
+          .put("F", "floatType")
+          .put("I", "intType")
+          .put("J", "longType")
+          .put("S", "shortType")
+          .put("V", "voidType")
+          .put("[Z", "booleanArrayType")
+          .put("[B", "byteArrayType")
+          .put("[C", "charArrayType")
+          .put("[D", "doubleArrayType")
+          .put("[F", "floatArrayType")
+          .put("[I", "intArrayType")
+          .put("[J", "longArrayType")
+          .put("[S", "shortArrayType")
+          .put("Ljava/lang/Object;", "objectType")
+          .put("Ljava/lang/Class;", "classType")
+          .put("Ljava/lang/Throwable;", "throwableType")
+          .put("Ljava/lang/String;", "stringType")
+          .put("Ljava/lang/Character;", "boxedCharType")
+          .put("Ljava/lang/CharSequence;", "charSequenceType")
+          .put("Ljava/lang/StringBuilder;", "stringBuilderType")
+          .put("Ljava/lang/AutoCloseable;", "autoCloseableType")
+          .build();
+
   private String dexType(DexType type) {
-    return "options.itemFactory.createType(" + quote(type.toDescriptorString()) + ")";
+    String descriptor = type.toDescriptorString();
+    String field = knownTypeFields.get(descriptor);
+    if (field != null) {
+      return "options.itemFactory." + field;
+    }
+    return "options.itemFactory.createSynthesizedType(" + quote(descriptor) + ")";
   }
 
   private String dexProto(DexProto proto) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 993363c..2992824 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -246,7 +246,14 @@
       if (options.encodeChecksums) {
         encodeChecksums(virtualFiles);
       }
+      // TODO(b/149190785): Only sort the live program!
+      if (appView != null) {
+        appView.appInfo().disableDefinitionForAssert();
+      }
       application.dexItemFactory.sort(namingLens);
+      if (appView != null) {
+        appView.appInfo().enableDefinitionForAssert();
+      }
       assert markers == null
           || markers.isEmpty()
           || application.dexItemFactory.extractMarkers() != null;
@@ -520,10 +527,10 @@
         // Append the annotations to annotations array of the class.
         DexAnnotation[] copy =
             ObjectArrays.concat(
-                clazz.annotations.annotations,
+                clazz.annotations().annotations,
                 annotations.toArray(DexAnnotation.EMPTY_ARRAY),
                 DexAnnotation.class);
-        clazz.annotations = new DexAnnotationSet(copy);
+        clazz.setAnnotations(new DexAnnotationSet(copy));
       }
 
       // Clear the attribute structures now that they are represented in annotations.
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 5cbd975..53f65b6 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -25,6 +25,7 @@
 import com.android.tools.r8.graph.DexEncodedAnnotation;
 import com.android.tools.r8.graph.DexEncodedArray;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItem;
@@ -38,7 +39,6 @@
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.IndexedDexItem;
-import com.android.tools.r8.graph.KeyedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
 import com.android.tools.r8.graph.PresortedComparable;
@@ -577,7 +577,7 @@
     }
   }
 
-  private <S extends Descriptor<T, S>, T extends KeyedDexItem<S>> void writeMemberAnnotations(
+  private <S extends Descriptor<T, S>, T extends DexEncodedMember<S>> void writeMemberAnnotations(
       List<T> items, ToIntFunction<T> getter) {
     for (T item : items) {
       dest.putInt(item.getKey().getOffset(mapping));
@@ -594,10 +594,10 @@
     dest.putInt(fieldAnnotations.size());
     dest.putInt(methodAnnotations.size());
     dest.putInt(parameterAnnotations.size());
-    writeMemberAnnotations(fieldAnnotations,
-        item -> mixedSectionOffsets.getOffsetFor(item.annotations));
-    writeMemberAnnotations(methodAnnotations,
-        item -> mixedSectionOffsets.getOffsetFor(item.annotations));
+    writeMemberAnnotations(
+        fieldAnnotations, item -> mixedSectionOffsets.getOffsetFor(item.annotations()));
+    writeMemberAnnotations(
+        methodAnnotations, item -> mixedSectionOffsets.getOffsetFor(item.annotations()));
     writeMemberAnnotations(parameterAnnotations,
         item -> mixedSectionOffsets.getOffsetFor(item.parameterAnnotationsList));
   }
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 03f0231..29a5995 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -29,7 +29,7 @@
 
   private final DexApplication app;
   private final DexItemFactory dexItemFactory;
-  private final ConcurrentHashMap<DexType, Map<Descriptor<?,?>, KeyedDexItem<?>>> definitions =
+  private final ConcurrentHashMap<DexType, Map<Descriptor<?, ?>, DexEncodedMember<?>>> definitions =
       new ConcurrentHashMap<>();
   // For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
   // class being optimized.
@@ -101,8 +101,8 @@
     return Collections.unmodifiableCollection(synthesizedClasses.values());
   }
 
-  private Map<Descriptor<?,?>, KeyedDexItem<?>> computeDefinitions(DexType type) {
-    Builder<Descriptor<?,?>, KeyedDexItem<?>> builder = ImmutableMap.builder();
+  private Map<Descriptor<?, ?>, DexEncodedMember<?>> computeDefinitions(DexType type) {
+    Builder<Descriptor<?, ?>, DexEncodedMember<?>> builder = ImmutableMap.builder();
     DexClass clazz = definitionFor(type);
     if (clazz != null) {
       clazz.forEachMethod(method -> builder.put(method.getKey(), method));
@@ -186,14 +186,15 @@
     return (DexEncodedField) getDefinitions(field.holder).get(field);
   }
 
-  private Map<Descriptor<?,?>, KeyedDexItem<?>> getDefinitions(DexType type) {
-    Map<Descriptor<?,?>, KeyedDexItem<?>> typeDefinitions = definitions.get(type);
+  private Map<Descriptor<?, ?>, DexEncodedMember<?>> getDefinitions(DexType type) {
+    Map<Descriptor<?, ?>, DexEncodedMember<?>> typeDefinitions = definitions.get(type);
     if (typeDefinitions != null) {
       return typeDefinitions;
     }
 
     typeDefinitions = computeDefinitions(type);
-    Map<Descriptor<?,?>, KeyedDexItem<?>> existing = definitions.putIfAbsent(type, typeDefinitions);
+    Map<Descriptor<?, ?>, DexEncodedMember<?>> existing =
+        definitions.putIfAbsent(type, typeDefinitions);
     return existing != null ? existing : typeDefinitions;
   }
 
@@ -673,4 +674,9 @@
     }
   }
 
+  // TODO(b/149190785): Remove once fixed.
+  public void enableDefinitionForAssert() {}
+
+  // TODO(b/149190785): Remove once fixed.
+  public void disableDefinitionForAssert() {}
 }
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index 6630f9c..cefb55a 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -4,12 +4,18 @@
 
 package com.android.tools.r8.graph;
 
+import static com.android.tools.r8.utils.TraversalContinuation.BREAK;
+import static com.android.tools.r8.utils.TraversalContinuation.CONTINUE;
+
 import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
+import com.android.tools.r8.utils.TraversalContinuation;
 import com.google.common.collect.Sets;
 import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
 
 /* Specific subclass of AppInfo designed to support desugaring in D8. Desugaring requires a
  * minimal amount of knowledge in the overall program, provided through classpath. Basic
@@ -37,6 +43,92 @@
     return this;
   }
 
+  /**
+   * Primitive traversal over all supertypes of a given type.
+   *
+   * <p>No order is guaranteed for the traversal, but a given type will be visited at most once. The
+   * given type is *not* visited. The function indicates if traversal should continue or break. The
+   * result of the traversal is BREAK iff the function returned BREAK.
+   */
+  public TraversalContinuation traverseSuperTypes(
+      final DexClass clazz, BiFunction<DexType, Boolean, TraversalContinuation> fn) {
+    // We do an initial zero-allocation pass over the class super chain as it does not require a
+    // worklist/seen-set. Only if the traversal is not aborted and there actually are interfaces,
+    // do we continue traversal over the interface types. This is assuming that the second pass
+    // over the super chain is less expensive than the eager allocation of the worklist.
+    int interfaceCount = 0;
+    {
+      DexClass currentClass = clazz;
+      while (currentClass != null) {
+        interfaceCount += currentClass.interfaces.values.length;
+        if (currentClass.superType == null) {
+          break;
+        }
+        TraversalContinuation stepResult = fn.apply(currentClass.superType, false);
+        if (stepResult.shouldBreak()) {
+          return stepResult;
+        }
+        currentClass = definitionFor(currentClass.superType);
+      }
+    }
+    if (interfaceCount == 0) {
+      return CONTINUE;
+    }
+    // Interfaces exist, create a worklist and seen set to ensure single visits.
+    Set<DexType> seen = Sets.newIdentityHashSet();
+    Deque<DexType> worklist = new ArrayDeque<>();
+    // Populate the worklist with the direct interfaces of the super chain.
+    {
+      DexClass currentClass = clazz;
+      while (currentClass != null) {
+        for (DexType iface : currentClass.interfaces.values) {
+          if (seen.add(iface)) {
+            TraversalContinuation stepResult = fn.apply(iface, true);
+            if (stepResult.shouldBreak()) {
+              return stepResult;
+            }
+            worklist.addLast(iface);
+          }
+        }
+        if (currentClass.superType == null) {
+          break;
+        }
+        currentClass = definitionFor(currentClass.superType);
+      }
+    }
+    // Iterate all interfaces.
+    while (!worklist.isEmpty()) {
+      DexType type = worklist.removeFirst();
+      DexClass definition = definitionFor(type);
+      if (definition != null) {
+        for (DexType iface : definition.interfaces.values) {
+          if (seen.add(iface)) {
+            TraversalContinuation stepResult = fn.apply(iface, true);
+            if (stepResult.shouldBreak()) {
+              return stepResult;
+            }
+            worklist.addLast(iface);
+          }
+        }
+      }
+    }
+    return CONTINUE;
+  }
+
+  /**
+   * Iterate each super type of class.
+   *
+   * <p>Same as traverseSuperTypes, but unconditionally visits all.
+   */
+  public void forEachSuperType(final DexClass clazz, BiConsumer<DexType, Boolean> fn) {
+    traverseSuperTypes(
+        clazz,
+        (type, isInterface) -> {
+          fn.accept(type, isInterface);
+          return CONTINUE;
+        });
+  }
+
   public boolean isSubtype(DexType subtype, DexType supertype) {
     assert subtype != null;
     assert supertype != null;
@@ -60,30 +152,15 @@
     if (!subtype.isClassType() || !supertype.isClassType()) {
       return false;
     }
-    Deque<DexType> workList = new ArrayDeque<>();
-    workList.addFirst(subtype);
-    while (!workList.isEmpty()) {
-      DexType type = workList.pollFirst();
-      DexClass subtypeClass = definitionFor(type);
-      if (subtypeClass == null) {
-        // Collect missing types for future reporting?
-        continue;
-      }
-      if (subtypeClass.superType == supertype) {
-        return true;
-      }
-      if (subtypeClass.superType != null) {
-        workList.add(subtypeClass.superType);
-      }
-      for (DexType itf : subtypeClass.interfaces.values) {
-        if (itf == supertype) {
-          return true;
-        }
-        workList.add(itf);
-      }
+    DexClass clazz = definitionFor(subtype);
+    if (clazz == null) {
+      return false;
     }
     // TODO(b/123506120): Report missing types when the predicate is inconclusive.
-    return false;
+    return traverseSuperTypes(
+            clazz,
+            (type, isInterface) -> type == supertype ? BREAK : CONTINUE)
+        .shouldBreak();
   }
 
   public boolean isRelatedBySubtyping(DexType type, DexType other) {
@@ -105,33 +182,16 @@
       return clazz.isInterface() ? Collections.singleton(type) : Collections.emptySet();
     }
 
-    // Slow path traverses the full hierarchy.
+    // Slow path traverses the full super type hierarchy.
     Set<DexType> interfaces = Sets.newIdentityHashSet();
     if (clazz.isInterface()) {
       interfaces.add(type);
     }
-    Deque<DexType> workList = new ArrayDeque<>();
-    if (clazz.superType != null && clazz.superType != dexItemFactory().objectType) {
-      workList.add(clazz.superType);
-    }
-    Collections.addAll(interfaces, clazz.interfaces.values);
-    Collections.addAll(workList, clazz.interfaces.values);
-    while (!workList.isEmpty()) {
-      DexType item = workList.pollFirst();
-      DexClass definition = definitionFor(item);
-      if (definition == null) {
-        // Collect missing types for future reporting?
-        continue;
+    forEachSuperType(clazz, (dexType, isInterface) -> {
+      if (isInterface) {
+        interfaces.add(dexType);
       }
-      if (definition.superType != null && definition.superType != dexItemFactory().objectType) {
-        workList.add(definition.superType);
-      }
-      for (DexType iface : definition.interfaces.values) {
-        if (interfaces.add(iface)) {
-          workList.add(iface);
-        }
-      }
-    }
+    });
     return interfaces;
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 63074c4..9f7b4cf 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
 import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
 import com.android.tools.r8.ir.optimize.CallSiteOptimizationInfoPropagator;
+import com.android.tools.r8.ir.optimize.library.LibraryMethodOptimizer;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
 import com.android.tools.r8.utils.InternalOptions;
@@ -50,6 +51,7 @@
 
   // Optimizations.
   private final CallSiteOptimizationInfoPropagator callSiteOptimizationInfoPropagator;
+  private final LibraryMethodOptimizer libraryMethodOptimizer;
   private final ProtoShrinker protoShrinker;
 
   // Optimization results.
@@ -92,6 +94,8 @@
       this.callSiteOptimizationInfoPropagator = null;
     }
 
+    this.libraryMethodOptimizer = new LibraryMethodOptimizer(this);
+
     if (enableWholeProgramOptimizations() && options.protoShrinking().isProtoShrinkingEnabled()) {
       this.protoShrinker = new ProtoShrinker(withLiveness());
     } else {
@@ -222,6 +226,10 @@
     return callSiteOptimizationInfoPropagator;
   }
 
+  public LibraryMethodOptimizer libraryMethodOptimizer() {
+    return libraryMethodOptimizer;
+  }
+
   public ProtoShrinker protoShrinker() {
     return protoShrinker;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
index 2ee2c0c..2a6154d 100644
--- a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
@@ -59,7 +59,7 @@
     ps.println("# Bytecode for");
     ps.println("# Class: '" + clazzName + "'");
     if (writeAllClassInfo) {
-      writeAnnotations(clazz.annotations, ps);
+      writeAnnotations(clazz.annotations(), ps);
       ps.println("# Flags: '" + clazz.accessFlags + "'");
       if (clazz.superType != application.dexItemFactory.objectType) {
         ps.println("# Extends: '" + clazz.superType.toSourceString() + "'");
@@ -87,7 +87,7 @@
       FieldSignature fieldSignature = naming != null
           ? naming.originalSignatureOf(field.field)
           : FieldSignature.fromDexField(field.field);
-      writeAnnotations(field.annotations, ps);
+      writeAnnotations(field.annotations(), ps);
       ps.print(field.accessFlags + " ");
       ps.println(fieldSignature);
     }
@@ -106,7 +106,7 @@
         : method.method.name.toString();
     ps.println("#");
     ps.println("# Method: '" + methodName + "':");
-    writeAnnotations(method.annotations, ps);
+    writeAnnotations(method.annotations(), ps);
     ps.println("# " + method.accessFlags);
     ps.println("#");
     ps.println();
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 0f60e07..50b4b2f 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -338,30 +338,25 @@
   }
 
   public static Collection<DexType> readAnnotationSynthesizedClassMap(
-      DexProgramClass programClass,
-      DexItemFactory dexItemFactory) {
-    DexAnnotation foundAnnotation = programClass.annotations.getFirstMatching(
-        dexItemFactory.annotationSynthesizedClassMap);
+      DexProgramClass clazz, DexItemFactory dexItemFactory) {
+    DexAnnotation foundAnnotation =
+        clazz.annotations().getFirstMatching(dexItemFactory.annotationSynthesizedClassMap);
     if (foundAnnotation != null) {
       if (foundAnnotation.annotation.elements.length != 1) {
-        throw new CompilationError(
-            getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+        throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
       }
       DexAnnotationElement value = foundAnnotation.annotation.elements[0];
       if (!value.name.toSourceString().equals("value")) {
-        throw new CompilationError(
-            getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+        throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
       }
       if (!(value.value instanceof DexValueArray)) {
-        throw new CompilationError(
-            getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+        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)) {
-          throw new CompilationError(
-              getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+          throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
         }
         synthesized.add(((DexValueType) element).value);
       }
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
index 1f2d9f1..e616e9e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -30,7 +30,7 @@
     parameterAnnotations = new ArrayList<>();
     while (methods.hasNext()) {
       DexEncodedMethod method = methods.next();
-      if (!method.annotations.isEmpty()) {
+      if (!method.annotations().isEmpty()) {
         methodAnnotations.add(method);
       }
       if (!method.parameterAnnotationsList.isEmpty()) {
@@ -44,14 +44,14 @@
     fieldAnnotations = new ArrayList<>();
     while (fields.hasNext()) {
       DexEncodedField field = fields.next();
-      if (!field.annotations.isEmpty()) {
+      if (!field.annotations().isEmpty()) {
         fieldAnnotations.add(field);
       }
     }
   }
 
   public DexAnnotationSet getClazzAnnotations() {
-    return clazz.annotations;
+    return clazz.annotations();
   }
 
   public List<DexEncodedMethod> getMethodAnnotations() {
@@ -83,7 +83,7 @@
       if (!other.clazz.hasOnlyInternalizableAnnotations()) {
         return false;
       }
-      return clazz.annotations.equals(other.clazz.annotations);
+      return clazz.annotations().equals(other.clazz.annotations());
     }
     return super.equals(obj);
   }
@@ -91,7 +91,7 @@
   @Override
   public final int hashCode() {
     if (classHasOnlyInternalizableAnnotations) {
-      return clazz.annotations.hashCode();
+      return clazz.annotations().hashCode();
     }
     return super.hashCode();
   }
@@ -108,8 +108,8 @@
   }
 
   private static <T extends PresortedComparable<T>> boolean isSorted(
-      List<? extends KeyedDexItem<T>> items) {
-    return isSorted(items, KeyedDexItem::getKey);
+      List<? extends DexEncodedMember<T>> items) {
+    return isSorted(items, DexEncodedMember::getKey);
   }
 
   private static <S, T extends Comparable<T>> boolean isSorted(
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
index 04251a6..dd24ed6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -6,12 +6,15 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.dex.MixedSectionCollection;
 import com.android.tools.r8.utils.ArrayUtils;
+import com.google.common.collect.Sets;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 public class DexAnnotationSet extends CachedHashValueDexItem {
 
@@ -33,7 +36,7 @@
   }
 
   public static DexType findDuplicateEntryType(List<DexAnnotation> annotations) {
-    Set<DexType> seenTypes = new HashSet<>();
+    Set<DexType> seenTypes = Sets.newIdentityHashSet();
     for (DexAnnotation annotation : annotations) {
       if (!seenTypes.add(annotation.annotation.type)) {
         return annotation.annotation.type;
@@ -46,6 +49,16 @@
     return THE_EMPTY_ANNOTATIONS_SET;
   }
 
+  public void forEach(Consumer<DexAnnotation> consumer) {
+    for (DexAnnotation annotation : annotations) {
+      consumer.accept(annotation);
+    }
+  }
+
+  public Stream<DexAnnotation> stream() {
+    return Arrays.stream(annotations);
+  }
+
   public int size() {
     return annotations.length;
   }
@@ -85,7 +98,7 @@
       assert sorted == sortedHashCode();
       return;
     }
-    Arrays.sort(annotations, (a, b) -> a.annotation.type.compareTo(b.annotation.type));
+    Arrays.sort(annotations, Comparator.comparing(a -> a.annotation.type));
     for (DexAnnotation annotation : annotations) {
       annotation.annotation.sort();
     }
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 321b5c7..3e1a144 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -69,8 +69,6 @@
   private NestHostClassAttribute nestHost;
   private final List<NestMemberClassAttribute> nestMembers;
 
-  public DexAnnotationSet annotations;
-
   public DexClass(
       DexString sourceFile,
       DexTypeList interfaces,
@@ -88,6 +86,7 @@
       DexAnnotationSet annotations,
       Origin origin,
       boolean skipNameValidationForTesting) {
+    super(annotations);
     assert origin != null;
     this.origin = origin;
     this.sourceFile = sourceFile;
@@ -104,7 +103,6 @@
     assert nestMembers != null;
     this.enclosingMethod = enclosingMethod;
     this.innerClasses = innerClasses;
-    this.annotations = annotations;
     if (type == superType) {
       throw new CompilationError("Class " + type.toString() + " cannot extend itself");
     }
@@ -131,6 +129,10 @@
         Iterables.filter(Arrays.asList(staticFields), predicate::test));
   }
 
+  public Iterable<DexEncodedMember<?>> members() {
+    return Iterables.concat(fields(), methods());
+  }
+
   public Iterable<DexEncodedMethod> methods() {
     return methods(Predicates.alwaysTrue());
   }
@@ -369,30 +371,13 @@
    * specified consumer.
    */
   public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
-    for (DexAnnotation annotation : annotations.annotations) {
-      consumer.accept(annotation);
-    }
-    for (DexEncodedMethod method : directMethods()) {
-      for (DexAnnotation annotation : method.annotations.annotations) {
-        consumer.accept(annotation);
-      }
+    annotations().forEach(consumer);
+    for (DexEncodedMethod method : methods()) {
+      method.annotations().forEach(consumer);
       method.parameterAnnotationsList.forEachAnnotation(consumer);
     }
-    for (DexEncodedMethod method : virtualMethods()) {
-      for (DexAnnotation annotation : method.annotations.annotations) {
-        consumer.accept(annotation);
-      }
-      method.parameterAnnotationsList.forEachAnnotation(consumer);
-    }
-    for (DexEncodedField field : instanceFields()) {
-      for (DexAnnotation annotation : field.annotations.annotations) {
-        consumer.accept(annotation);
-      }
-    }
-    for (DexEncodedField field : staticFields()) {
-      for (DexAnnotation annotation : field.annotations.annotations) {
-        consumer.accept(annotation);
-      }
+    for (DexEncodedField field : fields()) {
+      field.annotations().forEach(consumer);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinition.java b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
index df8a65f..dbf18c3 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinition.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
@@ -12,6 +12,25 @@
  */
 public abstract class DexDefinition extends DexItem {
 
+  private DexAnnotationSet annotations;
+
+  public DexDefinition(DexAnnotationSet annotations) {
+    assert annotations != null : "Should use DexAnnotationSet.THE_EMPTY_ANNOTATIONS_SET";
+    this.annotations = annotations;
+  }
+
+  public DexAnnotationSet annotations() {
+    return annotations;
+  }
+
+  public void clearAnnotations() {
+    setAnnotations(DexAnnotationSet.empty());
+  }
+
+  public void setAnnotations(DexAnnotationSet annotations) {
+    this.annotations = annotations;
+  }
+
   public boolean isDexClass() {
     return false;
   }
@@ -28,6 +47,14 @@
     return null;
   }
 
+  public boolean isDexEncodedMember() {
+    return false;
+  }
+
+  public DexEncodedMember<?> asDexEncodedMember() {
+    return null;
+  }
+
   public boolean isDexEncodedField() {
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index a920005..4f332f9 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -19,12 +19,11 @@
 import com.android.tools.r8.kotlin.KotlinMemberInfo;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
-public class DexEncodedField extends KeyedDexItem<DexField> {
+public class DexEncodedField extends DexEncodedMember<DexField> {
   public static final DexEncodedField[] EMPTY_ARRAY = {};
 
   public final DexField field;
   public final FieldAccessFlags accessFlags;
-  public DexAnnotationSet annotations;
   private DexValue staticValue;
 
   private FieldOptimizationInfo optimizationInfo = DefaultFieldOptimizationInfo.getInstance();
@@ -35,9 +34,9 @@
       FieldAccessFlags accessFlags,
       DexAnnotationSet annotations,
       DexValue staticValue) {
+    super(annotations);
     this.field = field;
     this.accessFlags = accessFlags;
-    this.annotations = annotations;
     this.staticValue = staticValue;
   }
 
@@ -84,7 +83,7 @@
   public void collectIndexedItems(
       IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
     field.collectIndexedItems(indexedItems, method, instructionOffset);
-    annotations.collectIndexedItems(indexedItems, method, instructionOffset);
+    annotations().collectIndexedItems(indexedItems, method, instructionOffset);
     if (accessFlags.isStatic()) {
       getStaticValue().collectIndexedItems(indexedItems, method, instructionOffset);
     }
@@ -92,7 +91,7 @@
 
   @Override
   void collectMixedSectionItems(MixedSectionCollection mixedItems) {
-    annotations.collectMixedSectionItems(mixedItems);
+    annotations().collectMixedSectionItems(mixedItems);
   }
 
   @Override
@@ -149,7 +148,7 @@
   }
 
   public boolean hasAnnotation() {
-    return !annotations.isEmpty();
+    return !annotations().isEmpty();
   }
 
   public boolean hasExplicitStaticValue() {
@@ -238,7 +237,7 @@
     if (this.field == field) {
       return this;
     }
-    DexEncodedField result = new DexEncodedField(field, accessFlags, annotations, staticValue);
+    DexEncodedField result = new DexEncodedField(field, accessFlags, annotations(), staticValue);
     result.optimizationInfo =
         optimizationInfo.isMutableFieldOptimizationInfo()
             ? optimizationInfo.asMutableFieldOptimizationInfo().mutableCopy()
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
new file mode 100644
index 0000000..6987227
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, 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.graph;
+
+public abstract class DexEncodedMember<T extends PresortedComparable<T>> extends DexDefinition {
+
+  public DexEncodedMember(DexAnnotationSet annotations) {
+    super(annotations);
+  }
+
+  public abstract T getKey();
+
+  @Override
+  public boolean isDexEncodedMember() {
+    return true;
+  }
+
+  @Override
+  public DexEncodedMember<?> asDexEncodedMember() {
+    return this;
+  }
+
+  @Override
+  public final boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    return other.getClass() == getClass()
+        && ((DexEncodedMember<?>) other).getKey().equals(getKey());
+  }
+
+  @Override
+  public final int hashCode() {
+    return getKey().hashCode();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 7af203c..184e15e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -76,7 +76,7 @@
 import java.util.function.IntPredicate;
 import org.objectweb.asm.Opcodes;
 
-public class DexEncodedMethod extends KeyedDexItem<DexMethod> {
+public class DexEncodedMethod extends DexEncodedMember<DexMethod> {
 
   public static final String CONFIGURATION_DEBUGGING_PREFIX = "Shaking error: Missing method in ";
 
@@ -118,15 +118,16 @@
 
   public static final DexEncodedMethod[] EMPTY_ARRAY = {};
   public static final DexEncodedMethod SENTINEL =
-      new DexEncodedMethod(null, null, null, ParameterAnnotationsList.empty(), null);
+      new DexEncodedMethod(
+          null, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null);
   public static final DexEncodedMethod ANNOTATION_REFERENCE =
-      new DexEncodedMethod(null, null, null, ParameterAnnotationsList.empty(), null);
+      new DexEncodedMethod(
+          null, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null);
   public static final Int2ReferenceMap<DebugLocalInfo> NO_PARAMETER_INFO =
       new Int2ReferenceArrayMap<>(0);
 
   public final DexMethod method;
   public final MethodAccessFlags accessFlags;
-  public DexAnnotationSet annotations;
   public ParameterAnnotationsList parameterAnnotationsList;
   private Code code;
   // TODO(b/128967328): towards finer-grained inlining constraints,
@@ -241,9 +242,9 @@
       Code code,
       int classFileVersion,
       boolean d8R8Synthesized) {
+    super(annotations);
     this.method = method;
     this.accessFlags = accessFlags;
-    this.annotations = annotations;
     this.parameterAnnotationsList = parameterAnnotationsList;
     this.code = code;
     this.classFileVersion = classFileVersion;
@@ -605,7 +606,7 @@
     if (code != null) {
       code.collectIndexedItems(indexedItems, this.method);
     }
-    annotations.collectIndexedItems(indexedItems);
+    annotations().collectIndexedItems(indexedItems);
     parameterAnnotationsList.collectIndexedItems(indexedItems);
   }
 
@@ -620,7 +621,7 @@
     if (code != null) {
       code.collectMixedSectionItems(mixedItems);
     }
-    annotations.collectMixedSectionItems(mixedItems);
+    annotations().collectMixedSectionItems(mixedItems);
     parameterAnnotationsList.collectMixedSectionItems(mixedItems);
   }
 
@@ -821,8 +822,8 @@
     DexProto proto = itemFactory.createProto(itemFactory.intType, args);
     DexMethod logMethod =
         itemFactory.createMethod(
-            itemFactory.createType("Landroid/util/Log;"), proto, itemFactory.createString("e"));
-    DexType exceptionType = itemFactory.createType("Ljava/lang/RuntimeException;");
+            itemFactory.androidUtilLogType, proto, itemFactory.createString("e"));
+    DexType exceptionType = itemFactory.runtimeExceptionType;
     DexMethod exceptionInitMethod =
         itemFactory.createMethod(
             exceptionType,
@@ -851,7 +852,7 @@
         itemFactory.createString(
             CONFIGURATION_DEBUGGING_PREFIX + method.holder.toSourceString() + ": " + signature);
     DexString tag = itemFactory.createString("[R8]");
-    DexType logger = itemFactory.createType("Ljava/util/logging/Logger;");
+    DexType logger = itemFactory.javaUtilLoggingLoggerType;
     DexMethod getLogger =
         itemFactory.createMethod(
             logger,
@@ -862,7 +863,7 @@
             logger,
             itemFactory.createProto(itemFactory.voidType, itemFactory.stringType),
             itemFactory.createString("severe"));
-    DexType exceptionType = itemFactory.createType("Ljava/lang/RuntimeException;");
+    DexType exceptionType = itemFactory.runtimeExceptionType;
     DexMethod exceptionInitMethod =
         itemFactory.createMethod(
             exceptionType,
@@ -1108,7 +1109,7 @@
     return new DexEncodedMethod(
         newMethod,
         newFlags,
-        target.annotations,
+        target.annotations(),
         target.parameterAnnotationsList,
         new SynthesizedCode(forwardSourceCodeBuilder::build),
         true);
@@ -1188,7 +1189,7 @@
 
   public boolean hasAnnotation() {
     checkIfObsolete();
-    return !annotations.isEmpty() || !parameterAnnotationsList.isEmpty();
+    return !annotations().isEmpty() || !parameterAnnotationsList.isEmpty();
   }
 
   public void registerCodeReferences(UseRegistry registry) {
@@ -1271,7 +1272,7 @@
       // Copy all the mutable state of a DexEncodedMethod here.
       method = from.method;
       accessFlags = from.accessFlags.copy();
-      annotations = from.annotations;
+      annotations = from.annotations();
       code = from.code;
       compilationState = from.compilationState;
       optimizationInfo = from.optimizationInfo.mutableCopy();
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index c38f7c6..df2402f 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -37,6 +37,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 import com.google.common.collect.Streams;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -61,6 +62,9 @@
 
   public static final String throwableDescriptorString = "Ljava/lang/Throwable;";
 
+  /** Set of types that may be synthesized during compilation. */
+  private final Set<DexType> possibleCompilerSynthesizedTypes = Sets.newIdentityHashSet();
+
   private final Map<DexString, DexString> strings = new ConcurrentHashMap<>();
   private final Map<DexString, DexType> types = new ConcurrentHashMap<>();
   private final Map<DexField, DexField> fields = new ConcurrentHashMap<>();
@@ -281,96 +285,120 @@
 
   public final DexString throwableArrayDescriptor = createString("[Ljava/lang/Throwable;");
 
-  public final DexType booleanType = createType(booleanDescriptor);
-  public final DexType byteType = createType(byteDescriptor);
-  public final DexType charType = createType(charDescriptor);
-  public final DexType doubleType = createType(doubleDescriptor);
-  public final DexType floatType = createType(floatDescriptor);
-  public final DexType intType = createType(intDescriptor);
-  public final DexType longType = createType(longDescriptor);
-  public final DexType shortType = createType(shortDescriptor);
-  public final DexType voidType = createType(voidDescriptor);
+  public final DexType booleanType = createStaticallyKnownType(booleanDescriptor);
+  public final DexType byteType = createStaticallyKnownType(byteDescriptor);
+  public final DexType charType = createStaticallyKnownType(charDescriptor);
+  public final DexType doubleType = createStaticallyKnownType(doubleDescriptor);
+  public final DexType floatType = createStaticallyKnownType(floatDescriptor);
+  public final DexType intType = createStaticallyKnownType(intDescriptor);
+  public final DexType longType = createStaticallyKnownType(longDescriptor);
+  public final DexType shortType = createStaticallyKnownType(shortDescriptor);
+  public final DexType voidType = createStaticallyKnownType(voidDescriptor);
 
-  public final DexType booleanArrayType = createType(booleanArrayDescriptor);
-  public final DexType byteArrayType = createType(byteArrayDescriptor);
-  public final DexType charArrayType = createType(charArrayDescriptor);
-  public final DexType doubleArrayType = createType(doubleArrayDescriptor);
-  public final DexType floatArrayType = createType(floatArrayDescriptor);
-  public final DexType intArrayType = createType(intArrayDescriptor);
-  public final DexType longArrayType = createType(longArrayDescriptor);
-  public final DexType shortArrayType = createType(shortArrayDescriptor);
+  public final DexType booleanArrayType = createStaticallyKnownType(booleanArrayDescriptor);
+   public final DexType byteArrayType = createStaticallyKnownType(byteArrayDescriptor);
+   public final DexType charArrayType = createStaticallyKnownType(charArrayDescriptor);
+   public final DexType doubleArrayType = createStaticallyKnownType(doubleArrayDescriptor);
+   public final DexType floatArrayType = createStaticallyKnownType(floatArrayDescriptor);
+   public final DexType intArrayType = createStaticallyKnownType(intArrayDescriptor);
+   public final DexType longArrayType = createStaticallyKnownType(longArrayDescriptor);
+   public final DexType shortArrayType = createStaticallyKnownType(shortArrayDescriptor);
 
-  public final DexType boxedBooleanType = createType(boxedBooleanDescriptor);
-  public final DexType boxedByteType = createType(boxedByteDescriptor);
-  public final DexType boxedCharType = createType(boxedCharDescriptor);
-  public final DexType boxedDoubleType = createType(boxedDoubleDescriptor);
-  public final DexType boxedFloatType = createType(boxedFloatDescriptor);
-  public final DexType boxedIntType = createType(boxedIntDescriptor);
-  public final DexType boxedLongType = createType(boxedLongDescriptor);
-  public final DexType boxedShortType = createType(boxedShortDescriptor);
-  public final DexType boxedNumberType = createType(boxedNumberDescriptor);
-  public final DexType boxedVoidType = createType(boxedVoidDescriptor);
+  public final DexType boxedBooleanType = createStaticallyKnownType(boxedBooleanDescriptor);
+  public final DexType boxedByteType = createStaticallyKnownType(boxedByteDescriptor);
+  public final DexType boxedCharType = createStaticallyKnownType(boxedCharDescriptor);
+  public final DexType boxedDoubleType = createStaticallyKnownType(boxedDoubleDescriptor);
+  public final DexType boxedFloatType = createStaticallyKnownType(boxedFloatDescriptor);
+  public final DexType boxedIntType = createStaticallyKnownType(boxedIntDescriptor);
+  public final DexType boxedLongType = createStaticallyKnownType(boxedLongDescriptor);
+  public final DexType boxedShortType = createStaticallyKnownType(boxedShortDescriptor);
+  public final DexType boxedNumberType = createStaticallyKnownType(boxedNumberDescriptor);
+  public final DexType boxedVoidType = createStaticallyKnownType(boxedVoidDescriptor);
 
-  public final DexType charSequenceType = createType(charSequenceDescriptor);
-  public final DexType charSequenceArrayType = createType(charSequenceArrayDescriptor);
-  public final DexType stringType = createType(stringDescriptor);
-  public final DexType stringArrayType = createType(stringArrayDescriptor);
-  public final DexType objectType = createType(objectDescriptor);
-  public final DexType objectArrayType = createType(objectArrayDescriptor);
-  public final DexType classArrayType = createType(classArrayDescriptor);
-  public final DexType enumType = createType(enumDescriptor);
-  public final DexType annotationType = createType(annotationDescriptor);
-  public final DexType objectsType = createType(objectsDescriptor);
-  public final DexType collectionsType = createType(collectionsDescriptor);
-  public final DexType iterableType = createType(iterableDescriptor);
-  public final DexType mathType = createType(mathDescriptor);
-  public final DexType strictMathType = createType(strictMathDescriptor);
-  public final DexType referenceFieldUpdaterType = createType(referenceFieldUpdaterDescriptor);
+  public final DexType charSequenceType = createStaticallyKnownType(charSequenceDescriptor);
+  public final DexType charSequenceArrayType =
+      createStaticallyKnownType(charSequenceArrayDescriptor);
+  public final DexType stringType = createStaticallyKnownType(stringDescriptor);
+  public final DexType stringArrayType = createStaticallyKnownType(stringArrayDescriptor);
+  public final DexType objectType = createStaticallyKnownType(objectDescriptor);
+  public final DexType objectArrayType = createStaticallyKnownType(objectArrayDescriptor);
+  public final DexType classArrayType = createStaticallyKnownType(classArrayDescriptor);
+  public final DexType enumType = createStaticallyKnownType(enumDescriptor);
+  public final DexType annotationType = createStaticallyKnownType(annotationDescriptor);
+  public final DexType objectsType = createStaticallyKnownType(objectsDescriptor);
+  public final DexType collectionsType = createStaticallyKnownType(collectionsDescriptor);
+  public final DexType iterableType = createStaticallyKnownType(iterableDescriptor);
+  public final DexType mathType = createStaticallyKnownType(mathDescriptor);
+  public final DexType strictMathType = createStaticallyKnownType(strictMathDescriptor);
+  public final DexType referenceFieldUpdaterType =
+      createStaticallyKnownType(referenceFieldUpdaterDescriptor);
 
-  public final DexType classType = createType(classDescriptor);
-  public final DexType classLoaderType = createType(classLoaderDescriptor);
-  public final DexType fieldType = createType(fieldDescriptor);
-  public final DexType methodType = createType(methodDescriptor);
-  public final DexType autoCloseableType = createType(autoCloseableDescriptor);
+  public final DexType classType = createStaticallyKnownType(classDescriptor);
+  public final DexType classLoaderType = createStaticallyKnownType(classLoaderDescriptor);
+  public final DexType fieldType = createStaticallyKnownType(fieldDescriptor);
+  public final DexType methodType = createStaticallyKnownType(methodDescriptor);
+  public final DexType autoCloseableType = createStaticallyKnownType(autoCloseableDescriptor);
 
-  public final DexType stringBuilderType = createType(stringBuilderDescriptor);
-  public final DexType stringBufferType = createType(stringBufferDescriptor);
+  public final DexType stringBuilderType = createStaticallyKnownType(stringBuilderDescriptor);
+  public final DexType stringBufferType = createStaticallyKnownType(stringBufferDescriptor);
 
-  public final DexType varHandleType = createType(varHandleDescriptor);
-  public final DexType methodHandleType = createType(methodHandleDescriptor);
-  public final DexType methodTypeType = createType(methodTypeDescriptor);
-  public final DexType invocationHandlerType = createType(invocationHandlerDescriptor);
-  public final DexType proxyType = createType(proxyDescriptor);
-  public final DexType serviceLoaderType = createType(serviceLoaderDescriptor);
+  public final DexType javaLangSystemType = createStaticallyKnownType("Ljava/lang/System;");
+  public final DexType javaIoPrintStreamType = createStaticallyKnownType("Ljava/io/PrintStream;");
+
+  public final DexType varHandleType = createStaticallyKnownType(varHandleDescriptor);
+  public final DexType methodHandleType = createStaticallyKnownType(methodHandleDescriptor);
+  public final DexType methodTypeType = createStaticallyKnownType(methodTypeDescriptor);
+  public final DexType invocationHandlerType =
+      createStaticallyKnownType(invocationHandlerDescriptor);
+  public final DexType proxyType = createStaticallyKnownType(proxyDescriptor);
+  public final DexType serviceLoaderType = createStaticallyKnownType(serviceLoaderDescriptor);
+
   public final DexType serviceLoaderConfigurationErrorType =
-      createType(serviceLoaderConfigurationErrorDescriptor);
-  public final DexType listType = createType(listDescriptor);
-  public final DexType setType = createType(setDescriptor);
-  public final DexType mapType = createType(mapDescriptor);
-  public final DexType mapEntryType = createType(mapEntryDescriptor);
-  public final DexType collectionType = createType(collectionDescriptor);
-  public final DexType comparatorType = createType(comparatorDescriptor);
-  public final DexType callableType = createType(callableDescriptor);
-  public final DexType supplierType = createType(supplierDescriptor);
-  public final DexType consumerType = createType(consumerDescriptor);
-  public final DexType runnableType = createType(runnableDescriptor);
-  public final DexType optionalType = createType(optionalDescriptor);
-  public final DexType optionalDoubleType = createType(optionalDoubleDescriptor);
-  public final DexType optionalIntType = createType(optionalIntDescriptor);
-  public final DexType optionalLongType = createType(optionalLongDescriptor);
-  public final DexType streamType = createType(streamDescriptor);
+      createStaticallyKnownType(serviceLoaderConfigurationErrorDescriptor);
+  public final DexType listType = createStaticallyKnownType(listDescriptor);
+  public final DexType setType = createStaticallyKnownType(setDescriptor);
+  public final DexType mapType = createStaticallyKnownType(mapDescriptor);
+  public final DexType mapEntryType = createStaticallyKnownType(mapEntryDescriptor);
+  public final DexType abstractMapSimpleEntryType =
+      createStaticallyKnownType("Ljava/util/AbstractMap$SimpleEntry;");
+  public final DexType collectionType = createStaticallyKnownType(collectionDescriptor);
+  public final DexType comparatorType = createStaticallyKnownType(comparatorDescriptor);
+  public final DexType callableType = createStaticallyKnownType(callableDescriptor);
+  public final DexType supplierType = createStaticallyKnownType(supplierDescriptor);
+  public final DexType consumerType = createStaticallyKnownType(consumerDescriptor);
+  public final DexType runnableType = createStaticallyKnownType(runnableDescriptor);
+  public final DexType optionalType = createStaticallyKnownType(optionalDescriptor);
+  public final DexType optionalDoubleType = createStaticallyKnownType(optionalDoubleDescriptor);
+  public final DexType optionalIntType = createStaticallyKnownType(optionalIntDescriptor);
+  public final DexType optionalLongType = createStaticallyKnownType(optionalLongDescriptor);
+  public final DexType streamType = createStaticallyKnownType(streamDescriptor);
 
-  public final DexType runtimeExceptionType = createType(runtimeExceptionDescriptor);
-  public final DexType throwableType = createType(throwableDescriptor);
-  public final DexType illegalAccessErrorType = createType(illegalAccessErrorDescriptor);
-  public final DexType icceType = createType(icceDescriptor);
+  public final DexType doubleConsumer =
+      createStaticallyKnownType("Ljava/util/function/DoubleConsumer;");
+  public final DexType longConsumer =
+      createStaticallyKnownType("Ljava/util/function/LongConsumer;");
+  public final DexType intConsumer = createStaticallyKnownType("Ljava/util/function/IntConsumer;");
+
+  public final DexType runtimeExceptionType = createStaticallyKnownType(runtimeExceptionDescriptor);
+  public final DexType throwableType = createStaticallyKnownType(throwableDescriptor);
+  public final DexType illegalAccessErrorType =
+      createStaticallyKnownType(illegalAccessErrorDescriptor);
+  public final DexType icceType = createStaticallyKnownType(icceDescriptor);
   public final DexType exceptionInInitializerErrorType =
-      createType(exceptionInInitializerErrorDescriptor);
-  public final DexType noClassDefFoundErrorType = createType(noClassDefFoundErrorDescriptor);
-  public final DexType noSuchFieldErrorType = createType(noSuchFieldErrorDescriptor);
-  public final DexType npeType = createType(npeDescriptor);
+      createStaticallyKnownType(exceptionInInitializerErrorDescriptor);
+  public final DexType noClassDefFoundErrorType =
+      createStaticallyKnownType(noClassDefFoundErrorDescriptor);
+  public final DexType noSuchFieldErrorType = createStaticallyKnownType(noSuchFieldErrorDescriptor);
+  public final DexType npeType = createStaticallyKnownType(npeDescriptor);
   public final DexType reflectiveOperationExceptionType =
-      createType(reflectiveOperationExceptionDescriptor);
+      createStaticallyKnownType(reflectiveOperationExceptionDescriptor);
+
+  public final DexType javaUtilLoggingLoggerType =
+      createStaticallyKnownType("Ljava/util/logging/Logger;");
+  public final DexType androidUtilLogType = createStaticallyKnownType("Landroid/util/Log;");
+
+  public final DexType androidOsBuildVersionType =
+      createStaticallyKnownType("Landroid/os/Build$VERSION;");
 
   public final StringBuildingMethods stringBuilderMethods =
       new StringBuildingMethods(stringBuilderType);
@@ -381,6 +409,7 @@
   public final ObjectMethods objectMethods = new ObjectMethods();
   public final StringMethods stringMethods = new StringMethods();
   public final LongMethods longMethods = new LongMethods();
+  public final DoubleMethods doubleMethods = new DoubleMethods();
   public final JavaUtilArraysMethods utilArraysMethods = new JavaUtilArraysMethods();
   public final ThrowableMethods throwableMethods = new ThrowableMethods();
   public final AssertionErrorMethods assertionErrorMethods = new AssertionErrorMethods();
@@ -402,50 +431,58 @@
 
   public final DexString deserializeLambdaMethodName = createString("$deserializeLambda$");
   public final DexProto deserializeLambdaMethodProto =
-      createProto(objectType, createType("Ljava/lang/invoke/SerializedLambda;"));
+      createProto(objectType, createStaticallyKnownType("Ljava/lang/invoke/SerializedLambda;"));
 
   // Dex system annotations.
   // See https://source.android.com/devices/tech/dalvik/dex-format.html#system-annotation
-  public final DexType annotationDefault = createType("Ldalvik/annotation/AnnotationDefault;");
-  public final DexType annotationEnclosingClass = createType("Ldalvik/annotation/EnclosingClass;");
-  public final DexType annotationEnclosingMethod = createType(
-      "Ldalvik/annotation/EnclosingMethod;");
-  public final DexType annotationInnerClass = createType("Ldalvik/annotation/InnerClass;");
-  public final DexType annotationMemberClasses = createType("Ldalvik/annotation/MemberClasses;");
-  public final DexType annotationMethodParameters = createType(
-      "Ldalvik/annotation/MethodParameters;");
-  public final DexType annotationSignature = createType("Ldalvik/annotation/Signature;");
-  public final DexType annotationSourceDebugExtension = createType(
-      "Ldalvik/annotation/SourceDebugExtension;");
-  public final DexType annotationThrows = createType("Ldalvik/annotation/Throws;");
+  public final DexType annotationDefault =
+      createStaticallyKnownType("Ldalvik/annotation/AnnotationDefault;");
+  public final DexType annotationEnclosingClass =
+      createStaticallyKnownType("Ldalvik/annotation/EnclosingClass;");
+  public final DexType annotationEnclosingMethod =
+      createStaticallyKnownType("Ldalvik/annotation/EnclosingMethod;");
+  public final DexType annotationInnerClass =
+      createStaticallyKnownType("Ldalvik/annotation/InnerClass;");
+  public final DexType annotationMemberClasses =
+      createStaticallyKnownType("Ldalvik/annotation/MemberClasses;");
+  public final DexType annotationMethodParameters =
+      createStaticallyKnownType("Ldalvik/annotation/MethodParameters;");
+  public final DexType annotationSignature =
+      createStaticallyKnownType("Ldalvik/annotation/Signature;");
+  public final DexType annotationSourceDebugExtension =
+      createStaticallyKnownType("Ldalvik/annotation/SourceDebugExtension;");
+  public final DexType annotationThrows = createStaticallyKnownType("Ldalvik/annotation/Throws;");
   public final DexType annotationSynthesizedClassMap =
-      createType("Lcom/android/tools/r8/annotations/SynthesizedClassMap;");
+      createStaticallyKnownType("Lcom/android/tools/r8/annotations/SynthesizedClassMap;");
   public final DexType annotationCovariantReturnType =
-      createType("Ldalvik/annotation/codegen/CovariantReturnType;");
+      createStaticallyKnownType("Ldalvik/annotation/codegen/CovariantReturnType;");
   public final DexType annotationCovariantReturnTypes =
-      createType("Ldalvik/annotation/codegen/CovariantReturnType$CovariantReturnTypes;");
+      createStaticallyKnownType(
+          "Ldalvik/annotation/codegen/CovariantReturnType$CovariantReturnTypes;");
   public final DexType annotationReachabilitySensitive =
-      createType("Ldalvik/annotation/optimization/ReachabilitySensitive;");
+      createStaticallyKnownType("Ldalvik/annotation/optimization/ReachabilitySensitive;");
 
   // Runtime affecting yet class-retained annotations.
   public final DexType dalvikFastNativeAnnotation =
-      createType("Ldalvik/annotation/optimization/FastNative;");
+      createStaticallyKnownType("Ldalvik/annotation/optimization/FastNative;");
   public final DexType dalvikCriticalNativeAnnotation =
-      createType("Ldalvik/annotation/optimization/CriticalNative;");
+      createStaticallyKnownType("Ldalvik/annotation/optimization/CriticalNative;");
 
   private static final String METAFACTORY_METHOD_NAME = "metafactory";
   private static final String METAFACTORY_ALT_METHOD_NAME = "altMetafactory";
 
-  public final DexType metafactoryType = createType("Ljava/lang/invoke/LambdaMetafactory;");
-  public final DexType callSiteType = createType("Ljava/lang/invoke/CallSite;");
-  public final DexType lookupType = createType("Ljava/lang/invoke/MethodHandles$Lookup;");
-  public final DexType iteratorType = createType("Ljava/util/Iterator;");
-  public final DexType listIteratorType = createType("Ljava/util/ListIterator;");
-  public final DexType enumerationType = createType("Ljava/util/Enumeration;");
-  public final DexType serializableType = createType("Ljava/io/Serializable;");
-  public final DexType externalizableType = createType("Ljava/io/Externalizable;");
-  public final DexType cloneableType = createType("Ljava/lang/Cloneable;");
-  public final DexType comparableType = createType("Ljava/lang/Comparable;");
+  public final DexType metafactoryType =
+      createStaticallyKnownType("Ljava/lang/invoke/LambdaMetafactory;");
+  public final DexType callSiteType = createStaticallyKnownType("Ljava/lang/invoke/CallSite;");
+  public final DexType lookupType =
+      createStaticallyKnownType("Ljava/lang/invoke/MethodHandles$Lookup;");
+  public final DexType iteratorType = createStaticallyKnownType("Ljava/util/Iterator;");
+  public final DexType listIteratorType = createStaticallyKnownType("Ljava/util/ListIterator;");
+  public final DexType enumerationType = createStaticallyKnownType("Ljava/util/Enumeration;");
+  public final DexType serializableType = createStaticallyKnownType("Ljava/io/Serializable;");
+  public final DexType externalizableType = createStaticallyKnownType("Ljava/io/Externalizable;");
+  public final DexType cloneableType = createStaticallyKnownType("Ljava/lang/Cloneable;");
+  public final DexType comparableType = createStaticallyKnownType("Ljava/lang/Comparable;");
 
   public final ServiceLoaderMethods serviceLoaderMethods = new ServiceLoaderMethods();
 
@@ -509,7 +546,7 @@
       createMethod(objectType, deserializeLambdaMethodProto, deserializeLambdaMethodName);
 
   public final DexType stringConcatFactoryType =
-      createType("Ljava/lang/invoke/StringConcatFactory;");
+      createStaticallyKnownType("Ljava/lang/invoke/StringConcatFactory;");
 
   public final DexMethod stringConcatWithConstantsMethod =
       createMethod(
@@ -633,6 +670,20 @@
     }
   }
 
+  public class DoubleMethods {
+
+    public final DexMethod isNaN;
+
+    private DoubleMethods() {
+      isNaN =
+          createMethod(
+              boxedDoubleDescriptor,
+              createString("isNaN"),
+              booleanDescriptor,
+              new DexString[] {doubleDescriptor});
+    }
+  }
+
   public class JavaUtilArraysMethods {
 
     public final DexMethod asList;
@@ -1315,20 +1366,60 @@
     return markers;
   }
 
-  synchronized public DexType createType(DexString descriptor) {
+  // Non-synchronized internal create.
+  private DexType internalCreateType(DexString descriptor) {
     assert !sorted;
     assert descriptor != null;
     DexType result = types.get(descriptor);
     if (result == null) {
       result = new DexType(descriptor);
-      assert result.isArrayType() || result.isClassType() || result.isPrimitiveType() ||
-          result.isVoidType();
+      assert result.isArrayType()
+          || result.isClassType()
+          || result.isPrimitiveType()
+          || result.isVoidType();
       assert !isInternalSentinel(result);
       types.put(descriptor, result);
     }
     return result;
   }
 
+  private DexType createStaticallyKnownType(String descriptor) {
+    return createStaticallyKnownType(createString(descriptor));
+  }
+
+  private DexType createStaticallyKnownType(DexString descriptor) {
+    DexType type = internalCreateType(descriptor);
+    // Conservatively add all statically known types to "compiler synthesized types set".
+    addPossiblySynthesizedType(type);
+    return type;
+  }
+
+  // Safe synchronized external create. May be used for statically known types in synthetic code.
+  // See the generated BackportedMethods.java for reference.
+  public synchronized DexType createSynthesizedType(String descriptor) {
+    DexType type = internalCreateType(createString(descriptor));
+    addPossiblySynthesizedType(type);
+    return type;
+  }
+
+  private void addPossiblySynthesizedType(DexType type) {
+    if (type.isArrayType()) {
+      type = type.toBaseType(this);
+    }
+    if (type.isClassType()) {
+      possibleCompilerSynthesizedTypes.add(type);
+    }
+  }
+
+  public void forEachPossiblyCompilerSynthesizedType(Consumer<DexType> fn) {
+    possibleCompilerSynthesizedTypes.forEach(fn);
+  }
+
+  // Safe synchronized external create. Should never be used to create a statically known type!
+  public synchronized DexType createType(DexString descriptor) {
+    return internalCreateType(descriptor);
+  }
+
   public DexType createType(String descriptor) {
     return createType(createString(descriptor));
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 5904f98..1ac7c58 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -148,9 +148,7 @@
       if (sourceFile != null) {
         sourceFile.collectIndexedItems(indexedItems, method, instructionOffset);
       }
-      if (annotations != null) {
-        annotations.collectIndexedItems(indexedItems, method, instructionOffset);
-      }
+      annotations().collectIndexedItems(indexedItems, method, instructionOffset);
       if (interfaces != null) {
         interfaces.collectIndexedItems(indexedItems, method, instructionOffset);
       }
@@ -203,13 +201,10 @@
       synchronizedCollectAll(collector, staticFields);
       synchronizedCollectAll(collector, instanceFields);
     }
-    if (annotations != null) {
-      annotations.collectMixedSectionItems(collector);
-    }
+    annotations().collectMixedSectionItems(collector);
     if (interfaces != null) {
       interfaces.collectMixedSectionItems(collector);
     }
-    annotations.collectMixedSectionItems(collector);
   }
 
   private static <T extends DexItem> void synchronizedCollectAll(MixedSectionCollection collection,
@@ -291,7 +286,7 @@
   }
 
   public boolean hasAnnotations() {
-    return !annotations.isEmpty()
+    return !annotations().isEmpty()
         || hasAnnotations(virtualMethods)
         || hasAnnotations(directMethods)
         || hasAnnotations(staticFields)
@@ -357,11 +352,11 @@
         && isSorted(instanceFields);
   }
 
-  private static <T extends KeyedDexItem<S>, S extends PresortedComparable<S>> boolean isSorted(
+  private static <T extends DexEncodedMember<S>, S extends PresortedComparable<S>> boolean isSorted(
       T[] items) {
     synchronized (items) {
       T[] sorted = items.clone();
-      Arrays.sort(sorted, Comparator.comparing(KeyedDexItem::getKey));
+      Arrays.sort(sorted, Comparator.comparing(DexEncodedMember::getKey));
       return Arrays.equals(items, sorted);
     }
   }
@@ -446,29 +441,8 @@
    * entire scope.
    */
   public boolean hasReachabilitySensitiveAnnotation(DexItemFactory factory) {
-    for (DexEncodedMethod directMethod : directMethods) {
-      for (DexAnnotation annotation : directMethod.annotations.annotations) {
-        if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
-          return true;
-        }
-      }
-    }
-    for (DexEncodedMethod virtualMethod : virtualMethods) {
-      for (DexAnnotation annotation : virtualMethod.annotations.annotations) {
-        if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
-          return true;
-        }
-      }
-    }
-    for (DexEncodedField staticField : staticFields) {
-      for (DexAnnotation annotation : staticField.annotations.annotations) {
-        if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
-          return true;
-        }
-      }
-    }
-    for (DexEncodedField instanceField : instanceFields) {
-      for (DexAnnotation annotation : instanceField.annotations.annotations) {
+    for (DexEncodedMember<?> member : members()) {
+      for (DexAnnotation annotation : member.annotations().annotations) {
         if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
           return true;
         }
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index 3e1ed8a..b8210c8 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -210,7 +210,7 @@
 
   public static class Builder extends DexApplication.Builder<Builder> {
 
-    private final ImmutableList<DexLibraryClass> libraryClasses;
+    private ImmutableList<DexLibraryClass> libraryClasses;
     private ImmutableList<DexClasspathClass> classpathClasses;
 
     Builder(LazyLoadedDexApplication application) {
@@ -233,6 +233,16 @@
       return this;
     }
 
+    public Builder replaceLibraryClasses(Collection<DexLibraryClass> libraryClasses) {
+      this.libraryClasses = ImmutableList.copyOf(libraryClasses);
+      return self();
+    }
+
+    public Builder replaceClasspathClasses(Collection<DexClasspathClass> classpathClasses) {
+      this.classpathClasses = ImmutableList.copyOf(classpathClasses);
+      return self();
+    }
+
     public Builder addClasspathClasses(List<DexClasspathClass> classes) {
       classpathClasses =
           ImmutableList.<DexClasspathClass>builder()
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index cf4a98e..eb17913 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -40,6 +40,7 @@
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.Iterables;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -475,13 +476,7 @@
     // or method is annotated, all methods get parsed with locals information.
     private void checkReachabilitySensitivity() {
       if (hasReachabilitySensitiveMethod || hasReachabilitySensitiveField()) {
-        for (DexEncodedMethod method : directMethods) {
-          Code code = method.getCode();
-          if (code != null && code.isCfCode()) {
-            code.asLazyCfCode().markReachabilitySensitive();
-          }
-        }
-        for (DexEncodedMethod method : virtualMethods) {
+        for (DexEncodedMethod method : Iterables.concat(directMethods, virtualMethods)) {
           Code code = method.getCode();
           if (code != null && code.isCfCode()) {
             code.asLazyCfCode().markReachabilitySensitive();
@@ -492,15 +487,8 @@
 
     private boolean hasReachabilitySensitiveField() {
       DexType reachabilitySensitive = application.getFactory().annotationReachabilitySensitive;
-      for (DexEncodedField field : instanceFields) {
-        for (DexAnnotation annotation : field.annotations.annotations) {
-          if (annotation.annotation.type == reachabilitySensitive) {
-            return true;
-          }
-        }
-      }
-      for (DexEncodedField field : staticFields) {
-        for (DexAnnotation annotation : field.annotations.annotations) {
+      for (DexEncodedField field : Iterables.concat(instanceFields, staticFields)) {
+        for (DexAnnotation annotation : field.annotations().annotations) {
           if (annotation.annotation.type == reachabilitySensitive) {
             return true;
           }
diff --git a/src/main/java/com/android/tools/r8/graph/KeyedDexItem.java b/src/main/java/com/android/tools/r8/graph/KeyedDexItem.java
deleted file mode 100644
index 239a85d..0000000
--- a/src/main/java/com/android/tools/r8/graph/KeyedDexItem.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2016, 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.graph;
-
-public abstract class KeyedDexItem<T extends PresortedComparable<T>> extends DexDefinition {
-
-  public abstract T getKey();
-
-  @Override
-  public final boolean equals(Object other) {
-    if (other == this) {
-      return true;
-    }
-    return (other.getClass() == getClass()) && ((KeyedDexItem<?>) other).getKey().equals(getKey());
-  }
-
-  @Override
-  public final int hashCode() {
-    return getKey().hashCode();
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/graph/LookupResult.java b/src/main/java/com/android/tools/r8/graph/LookupResult.java
new file mode 100644
index 0000000..7a923de
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/LookupResult.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2020, 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.graph;
+
+import com.android.tools.r8.graph.LookupResult.LookupResultSuccess.LookupResultCollectionState;
+import java.util.Collections;
+import java.util.Set;
+
+public abstract class LookupResult {
+
+  public boolean isLookupResultFailure() {
+    return false;
+  }
+
+  public boolean isLookupResultSuccess() {
+    return false;
+  }
+
+  public LookupResultFailure asLookupResultFailure() {
+    return null;
+  }
+
+  public LookupResultSuccess asLookupResultSuccess() {
+    return null;
+  }
+
+  public static LookupResultSuccess createResult(
+      Set<DexEncodedMethod> methodTargets, LookupResultCollectionState state) {
+    return new LookupResultSuccess(methodTargets, state);
+  }
+
+  public static LookupResultFailure createFailedResult() {
+    return LookupResultFailure.INSTANCE;
+  }
+
+  public static LookupResultSuccess getIncompleteEmptyResult() {
+    return LookupResultSuccess.EMPTY_INSTANCE;
+  }
+
+  public static class LookupResultSuccess extends LookupResult {
+
+    private static final LookupResultSuccess EMPTY_INSTANCE =
+        new LookupResultSuccess(Collections.emptySet(), LookupResultCollectionState.Incomplete);
+
+    private final Set<DexEncodedMethod> methodTargets;
+    private final LookupResultCollectionState state;
+
+    private LookupResultSuccess(
+        Set<DexEncodedMethod> methodTargets, LookupResultCollectionState state) {
+      this.methodTargets = methodTargets;
+      this.state = state;
+    }
+
+    public boolean isEmpty() {
+      return methodTargets == null || methodTargets.isEmpty();
+    }
+
+    public Set<DexEncodedMethod> getMethodTargets() {
+      return methodTargets;
+    }
+
+    @Override
+    public LookupResultSuccess asLookupResultSuccess() {
+      return this;
+    }
+
+    @Override
+    public boolean isLookupResultSuccess() {
+      return true;
+    }
+
+    public boolean isIncomplete() {
+      return state == LookupResultCollectionState.Incomplete;
+    }
+
+    public enum LookupResultCollectionState {
+      Complete,
+      Incomplete,
+    }
+  }
+
+  public static class LookupResultFailure extends LookupResult {
+
+    private static final LookupResultFailure INSTANCE = new LookupResultFailure();
+
+    private LookupResultFailure() {
+      // Empty to only allow creation locally.
+    }
+
+    @Override
+    public LookupResultFailure asLookupResultFailure() {
+      return this;
+    }
+
+    @Override
+    public boolean isLookupResultFailure() {
+      return true;
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
new file mode 100644
index 0000000..2ed505e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, 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.graph;
+
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+/**
+ * Provides immutable access to {@link ObjectAllocationInfoCollectionImpl}, which stores the set of
+ * instantiated classes along with their allocation sites.
+ */
+public interface ObjectAllocationInfoCollection {
+
+  void forEachClassWithKnownAllocationSites(
+      BiConsumer<DexProgramClass, Set<DexEncodedMethod>> consumer);
+
+  boolean isAllocationSitesKnown(DexProgramClass clazz);
+
+  boolean isInstantiatedDirectly(DexProgramClass clazz);
+
+  ObjectAllocationInfoCollection rewrittenWithLens(
+      DexDefinitionSupplier definitions, GraphLense lens);
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
new file mode 100644
index 0000000..fa13c74
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
@@ -0,0 +1,165 @@
+// Copyright (c) 2020, 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.graph;
+
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
+
+import com.android.tools.r8.shaking.GraphReporter;
+import com.android.tools.r8.shaking.InstantiationReason;
+import com.android.tools.r8.shaking.KeepReason;
+import com.android.tools.r8.utils.LensUtils;
+import com.google.common.collect.Sets;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+/** Stores the set of instantiated classes along with their allocation sites. */
+public class ObjectAllocationInfoCollectionImpl implements ObjectAllocationInfoCollection {
+
+  private final Map<DexProgramClass, Set<DexEncodedMethod>> classesWithAllocationSiteTracking;
+  private final Set<DexProgramClass> classesWithoutAllocationSiteTracking;
+
+  private ObjectAllocationInfoCollectionImpl(
+      Map<DexProgramClass, Set<DexEncodedMethod>> classesWithAllocationSiteTracking,
+      Set<DexProgramClass> classesWithoutAllocationSiteTracking) {
+    this.classesWithAllocationSiteTracking = classesWithAllocationSiteTracking;
+    this.classesWithoutAllocationSiteTracking = classesWithoutAllocationSiteTracking;
+  }
+
+  public static Builder builder(boolean trackAllocationSites, GraphReporter reporter) {
+    return new Builder(trackAllocationSites, reporter);
+  }
+
+  @Override
+  public void forEachClassWithKnownAllocationSites(
+      BiConsumer<DexProgramClass, Set<DexEncodedMethod>> consumer) {
+    classesWithAllocationSiteTracking.forEach(consumer);
+  }
+
+  @Override
+  public boolean isAllocationSitesKnown(DexProgramClass clazz) {
+    return classesWithAllocationSiteTracking.containsKey(clazz);
+  }
+
+  @Override
+  public boolean isInstantiatedDirectly(DexProgramClass clazz) {
+    if (classesWithAllocationSiteTracking.containsKey(clazz)) {
+      assert !classesWithAllocationSiteTracking.get(clazz).isEmpty();
+      return true;
+    }
+    return classesWithoutAllocationSiteTracking.contains(clazz);
+  }
+
+  @Override
+  public ObjectAllocationInfoCollectionImpl rewrittenWithLens(
+      DexDefinitionSupplier definitions, GraphLense lens) {
+    return builder(true, null).rewrittenWithLens(this, definitions, lens).build();
+  }
+
+  public static class Builder {
+
+    private final boolean trackAllocationSites;
+
+    private final Map<DexProgramClass, Set<DexEncodedMethod>> classesWithAllocationSiteTracking =
+        new IdentityHashMap<>();
+    private final Set<DexProgramClass> classesWithoutAllocationSiteTracking =
+        Sets.newIdentityHashSet();
+
+    private GraphReporter reporter;
+
+    private Builder(boolean trackAllocationSites, GraphReporter reporter) {
+      this.trackAllocationSites = trackAllocationSites;
+      this.reporter = reporter;
+    }
+
+    private boolean shouldTrackAllocationSitesForClass(
+        DexProgramClass clazz, InstantiationReason instantiationReason) {
+      if (!trackAllocationSites) {
+        return false;
+      }
+      if (instantiationReason != InstantiationReason.NEW_INSTANCE_INSTRUCTION) {
+        // There is an allocation site which is not a new-instance instruction.
+        return false;
+      }
+      if (classesWithoutAllocationSiteTracking.contains(clazz)) {
+        // We already gave up on tracking the allocation sites for `clazz` previously.
+        return false;
+      }
+      // We currently only use allocation site information for instance field value propagation.
+      return !clazz.instanceFields().isEmpty();
+    }
+
+    public boolean isInstantiatedDirectly(DexProgramClass clazz) {
+      if (classesWithAllocationSiteTracking.containsKey(clazz)) {
+        assert !classesWithAllocationSiteTracking.get(clazz).isEmpty();
+        return true;
+      }
+      return classesWithoutAllocationSiteTracking.contains(clazz);
+    }
+
+    /**
+     * Records that {@param clazz} is instantiated in {@param context}.
+     *
+     * @return true if {@param clazz} was not instantiated before.
+     */
+    public boolean recordDirectAllocationSite(
+        DexProgramClass clazz,
+        DexEncodedMethod context,
+        InstantiationReason instantiationReason,
+        KeepReason keepReason) {
+      assert !clazz.isInterface();
+      if (reporter != null) {
+        reporter.registerClass(clazz, keepReason);
+      }
+      if (shouldTrackAllocationSitesForClass(clazz, instantiationReason)) {
+        assert context != null;
+        Set<DexEncodedMethod> allocationSitesForClass =
+            classesWithAllocationSiteTracking.computeIfAbsent(
+                clazz, ignore -> Sets.newIdentityHashSet());
+        allocationSitesForClass.add(context);
+        return allocationSitesForClass.size() == 1;
+      }
+      if (classesWithoutAllocationSiteTracking.add(clazz)) {
+        Set<DexEncodedMethod> allocationSitesForClass =
+            classesWithAllocationSiteTracking.remove(clazz);
+        return allocationSitesForClass == null;
+      }
+      return false;
+    }
+
+    Builder rewrittenWithLens(
+        ObjectAllocationInfoCollectionImpl objectAllocationInfos,
+        DexDefinitionSupplier definitions,
+        GraphLense lens) {
+      objectAllocationInfos.classesWithAllocationSiteTracking.forEach(
+          (clazz, allocationSitesForClass) -> {
+            DexProgramClass rewrittenClass =
+                asProgramClassOrNull(definitions.definitionFor(lens.lookupType(clazz.type)));
+            assert rewrittenClass != null;
+            assert !classesWithAllocationSiteTracking.containsKey(rewrittenClass);
+            classesWithAllocationSiteTracking.put(
+                rewrittenClass,
+                LensUtils.rewrittenWithRenamedSignature(
+                    allocationSitesForClass, definitions, lens));
+          });
+      objectAllocationInfos.classesWithoutAllocationSiteTracking.forEach(
+          clazz -> {
+            DexProgramClass rewrittenClass =
+                asProgramClassOrNull(definitions.definitionFor(lens.lookupType(clazz.type)));
+            assert rewrittenClass != null;
+            assert !classesWithAllocationSiteTracking.containsKey(rewrittenClass);
+            assert !classesWithoutAllocationSiteTracking.contains(rewrittenClass);
+            classesWithoutAllocationSiteTracking.add(rewrittenClass);
+          });
+      return this;
+    }
+
+    public ObjectAllocationInfoCollectionImpl build() {
+      return new ObjectAllocationInfoCollectionImpl(
+          classesWithAllocationSiteTracking, classesWithoutAllocationSiteTracking);
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/PresortedComparable.java b/src/main/java/com/android/tools/r8/graph/PresortedComparable.java
index 563b40a..81e6d56 100644
--- a/src/main/java/com/android/tools/r8/graph/PresortedComparable.java
+++ b/src/main/java/com/android/tools/r8/graph/PresortedComparable.java
@@ -11,8 +11,8 @@
 public interface PresortedComparable<T> extends Presorted, Comparable<T> {
 
   static <T extends PresortedComparable<T>> boolean isSorted(
-      List<? extends KeyedDexItem<T>> items) {
-    return isSorted(items, KeyedDexItem::getKey);
+      List<? extends DexEncodedMember<T>> items) {
+    return isSorted(items, DexEncodedMember::getKey);
   }
 
   static <S, T extends Comparable<T>> boolean isSorted(S[] items, Function<S, T> getter) {
diff --git a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
index f3f308f..c2bd3a4 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -4,6 +4,9 @@
 package com.android.tools.r8.graph;
 
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.LiveSubTypeInfo.LiveSubTypeResult;
+import com.android.tools.r8.graph.LookupResult.LookupResultSuccess.LookupResultCollectionState;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.SetUtils;
 import com.google.common.collect.Sets;
 import java.util.Collection;
@@ -75,7 +78,12 @@
   public abstract DexEncodedMethod lookupInvokeStaticTarget(
       DexProgramClass context, AppInfoWithClassHierarchy appInfo);
 
-  public abstract Set<DexEncodedMethod> lookupVirtualDispatchTargets(AppInfoWithSubtyping appInfo);
+  public abstract LookupResult lookupVirtualDispatchTargets(
+      AppView<?> appView, LiveSubTypeInfo liveSubTypes);
+
+  public final LookupResult lookupVirtualDispatchTargets(AppView<AppInfoWithLiveness> appView) {
+    return lookupVirtualDispatchTargets(appView, appView.appInfo());
+  }
 
   /** Result for a resolution that succeeds with a known declaration/definition. */
   public static class SingleResolutionResult extends ResolutionResult {
@@ -322,19 +330,21 @@
     }
 
     @Override
-    public Set<DexEncodedMethod> lookupVirtualDispatchTargets(AppInfoWithSubtyping appInfo) {
+    public LookupResult lookupVirtualDispatchTargets(
+        AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
       return initialResolutionHolder.isInterface()
-          ? lookupInterfaceTargets(appInfo)
-          : lookupVirtualTargets(appInfo);
+          ? lookupInterfaceTargets(appView, liveSubTypeInfo)
+          : lookupVirtualTargets(appView, liveSubTypeInfo);
     }
 
     // TODO(b/140204899): Leverage refined receiver type if available.
-    private Set<DexEncodedMethod> lookupVirtualTargets(AppInfoWithSubtyping appInfo) {
+    private LookupResult lookupVirtualTargets(AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
       assert !initialResolutionHolder.isInterface();
       if (resolvedMethod.isPrivateMethod()) {
         // If the resolved reference is private there is no dispatch.
         // This is assuming that the method is accessible, which implies self/nest access.
-        return Collections.singleton(resolvedMethod);
+        return LookupResult.createResult(
+            Collections.singleton(resolvedMethod), LookupResultCollectionState.Complete);
       }
       assert resolvedMethod.isNonPrivateVirtualMethod();
       // First add the target for receiver type method.type.
@@ -343,27 +353,29 @@
       DexMethod method = resolvedMethod.method;
       // TODO(b/140204899): Instead of subtypes of holder, we could iterate subtypes of refined
       //   receiver type if available.
-      for (DexType type : appInfo.subtypes(method.holder)) {
-        DexClass clazz = appInfo.definitionFor(type);
-        if (!clazz.isInterface()) {
-          ResolutionResult methods = appInfo.resolveMethodOnClass(clazz, method);
+      for (DexProgramClass programClass :
+          liveSubTypeInfo.getLiveSubTypes(method.holder).getProgramClasses()) {
+        if (!programClass.isInterface()) {
+          ResolutionResult methods = appView.appInfo().resolveMethodOnClass(programClass, method);
           DexEncodedMethod target = methods.getSingleTarget();
           if (target != null && target.isNonPrivateVirtualMethod()) {
             result.add(target);
           }
         }
       }
-      return result;
+      return LookupResult.createResult(result, LookupResultCollectionState.Complete);
     }
 
     // TODO(b/140204899): Leverage refined receiver type if available.
-    private Set<DexEncodedMethod> lookupInterfaceTargets(AppInfoWithSubtyping appInfo) {
+    private LookupResult lookupInterfaceTargets(
+        AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
       assert initialResolutionHolder.isInterface();
       if (resolvedMethod.isPrivateMethod()) {
         // If the resolved reference is private there is no dispatch.
         // This is assuming that the method is accessible, which implies self/nest access.
         assert resolvedMethod.hasCode();
-        return Collections.singleton(resolvedMethod);
+        return LookupResult.createResult(
+            Collections.singleton(resolvedMethod), LookupResultCollectionState.Complete);
       }
       assert resolvedMethod.isNonPrivateVirtualMethod();
       Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
@@ -389,7 +401,7 @@
       //     public void bar() { }
       //   }
       //
-      addIfDefaultMethodWithLambdaInstantiations(appInfo, resolvedMethod, result);
+      addIfDefaultMethodWithLambdaInstantiations(liveSubTypeInfo, resolvedMethod, result);
 
       DexMethod method = resolvedMethod.method;
       Consumer<DexEncodedMethod> addIfNotAbstract =
@@ -410,35 +422,38 @@
 
       // TODO(b/140204899): Instead of subtypes of holder, we could iterate subtypes of refined
       //   receiver type if available.
-      for (DexType type : appInfo.subtypes(method.holder)) {
-        DexClass clazz = appInfo.definitionFor(type);
+      for (DexProgramClass clazz :
+          liveSubTypeInfo.getLiveSubTypes(method.holder).getProgramClasses()) {
         if (clazz.isInterface()) {
-          ResolutionResult targetMethods = appInfo.resolveMethodOnInterface(clazz, method);
+          ResolutionResult targetMethods =
+              appView.appInfo().resolveMethodOnInterface(clazz, method);
           if (targetMethods.isSingleResolution()) {
             // Sub-interfaces can have default implementations that override the resolved method.
             // Therefore we have to add default methods in sub interfaces.
             DexEncodedMethod singleTarget = targetMethods.getSingleTarget();
-            addIfDefaultMethodWithLambdaInstantiations(appInfo, singleTarget, result);
+            addIfDefaultMethodWithLambdaInstantiations(liveSubTypeInfo, singleTarget, result);
             addIfNotAbstractAndBridge.accept(singleTarget);
           }
         } else {
-          ResolutionResult targetMethods = appInfo.resolveMethodOnClass(clazz, method);
+          ResolutionResult targetMethods = appView.appInfo().resolveMethodOnClass(clazz, method);
           if (targetMethods.isSingleResolution()) {
             addIfNotAbstract.accept(targetMethods.getSingleTarget());
           }
         }
       }
-      return result;
+      return LookupResult.createResult(result, LookupResultCollectionState.Complete);
     }
 
     private void addIfDefaultMethodWithLambdaInstantiations(
-        AppInfoWithSubtyping appInfo, DexEncodedMethod method, Set<DexEncodedMethod> result) {
+        LiveSubTypeInfo liveSubTypesInfo, DexEncodedMethod method, Set<DexEncodedMethod> result) {
       if (method == null) {
         return;
       }
       if (method.hasCode()) {
-        DexProgramClass holder = appInfo.definitionForProgramType(method.method.holder);
-        if (appInfo.hasAnyInstantiatedLambdas(holder)) {
+        LiveSubTypeResult liveSubTypes = liveSubTypesInfo.getLiveSubTypes(method.method.holder);
+        // TODO(b/148769279): The below is basically if (true), but should be changed when we
+        //  have live sub type information.
+        if (liveSubTypes.getCallSites() == null || liveSubTypes.getCallSites() != null) {
           result.add(method);
         }
       }
@@ -472,8 +487,9 @@
     }
 
     @Override
-    public Set<DexEncodedMethod> lookupVirtualDispatchTargets(AppInfoWithSubtyping appInfo) {
-      return null;
+    public LookupResult lookupVirtualDispatchTargets(
+        AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
+      return LookupResult.getIncompleteEmptyResult();
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
index 35bbf2f..29dc41b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
@@ -43,7 +43,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
-public class FieldValueAnalysis {
+public abstract class FieldValueAnalysis {
 
   private final AppView<AppInfoWithLiveness> appView;
   private final DexProgramClass clazz;
@@ -53,7 +53,7 @@
 
   private Map<BasicBlock, AbstractFieldSet> fieldsMaybeReadBeforeBlockInclusiveCache;
 
-  private FieldValueAnalysis(
+  FieldValueAnalysis(
       AppView<AppInfoWithLiveness> appView,
       IRCode code,
       OptimizationFeedback feedback,
@@ -68,37 +68,6 @@
     this.method = method;
   }
 
-  public static void run(
-      AppView<?> appView,
-      IRCode code,
-      ClassInitializerDefaultsResult classInitializerDefaultsResult,
-      OptimizationFeedback feedback,
-      DexEncodedMethod method) {
-    if (!appView.enableWholeProgramOptimizations()) {
-      return;
-    }
-    assert appView.appInfo().hasLiveness();
-    if (!method.isInitializer()) {
-      return;
-    }
-    DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
-    if (method.isInstanceInitializer()) {
-      if (!appView.options().enableValuePropagationForInstanceFields) {
-        return;
-      }
-      DexEncodedMethod otherInstanceInitializer =
-          clazz.lookupDirectMethod(other -> other.isInstanceInitializer() && other != method);
-      if (otherInstanceInitializer != null) {
-        // Conservatively bail out.
-        // TODO(b/125282093): Handle multiple instance initializers on the same class.
-        return;
-      }
-    }
-
-    new FieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
-        .computeFieldOptimizationInfo(classInitializerDefaultsResult);
-  }
-
   private Map<BasicBlock, AbstractFieldSet> getOrCreateFieldsMaybeReadBeforeBlockInclusive() {
     if (fieldsMaybeReadBeforeBlockInclusiveCache == null) {
       fieldsMaybeReadBeforeBlockInclusiveCache = createFieldsMaybeReadBeforeBlockInclusive();
@@ -107,8 +76,7 @@
   }
 
   /** This method analyzes initializers with the purpose of computing field optimization info. */
-  private void computeFieldOptimizationInfo(
-      ClassInitializerDefaultsResult classInitializerDefaultsResult) {
+  void computeFieldOptimizationInfo(ClassInitializerDefaultsResult classInitializerDefaultsResult) {
     AppInfoWithLiveness appInfo = appView.appInfo();
     DominatorTree dominatorTree = null;
 
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
new file mode 100644
index 0000000..d636715
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, 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.ir.analysis.fieldvalueanalysis;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class InstanceFieldValueAnalysis extends FieldValueAnalysis {
+
+  private InstanceFieldValueAnalysis(
+      AppView<AppInfoWithLiveness> appView,
+      IRCode code,
+      OptimizationFeedback feedback,
+      DexProgramClass clazz,
+      DexEncodedMethod method) {
+    super(appView, code, feedback, clazz, method);
+  }
+
+  public static void run(
+      AppView<?> appView,
+      IRCode code,
+      ClassInitializerDefaultsResult classInitializerDefaultsResult,
+      OptimizationFeedback feedback,
+      DexEncodedMethod method) {
+    assert appView.appInfo().hasLiveness();
+    assert appView.enableWholeProgramOptimizations();
+    assert method.isInstanceInitializer();
+    DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
+    if (!appView.options().enableValuePropagationForInstanceFields) {
+      return;
+    }
+    DexEncodedMethod otherInstanceInitializer =
+        clazz.lookupDirectMethod(other -> other.isInstanceInitializer() && other != method);
+    if (otherInstanceInitializer != null) {
+      // Conservatively bail out.
+      // TODO(b/125282093): Handle multiple instance initializers on the same class.
+      return;
+    }
+    new InstanceFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
+        .computeFieldOptimizationInfo(classInitializerDefaultsResult);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
new file mode 100644
index 0000000..0c91855
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, 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.ir.analysis.fieldvalueanalysis;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class StaticFieldValueAnalysis extends FieldValueAnalysis {
+
+  private StaticFieldValueAnalysis(
+      AppView<AppInfoWithLiveness> appView,
+      IRCode code,
+      OptimizationFeedback feedback,
+      DexProgramClass clazz,
+      DexEncodedMethod method) {
+    super(appView, code, feedback, clazz, method);
+  }
+
+  public static void run(
+      AppView<?> appView,
+      IRCode code,
+      ClassInitializerDefaultsResult classInitializerDefaultsResult,
+      OptimizationFeedback feedback,
+      DexEncodedMethod method) {
+    assert appView.appInfo().hasLiveness();
+    assert appView.enableWholeProgramOptimizations();
+    assert method.isClassInitializer();
+    DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
+    new StaticFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
+        .computeFieldOptimizationInfo(classInitializerDefaultsResult);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
index 9b980b9..0596d7b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
@@ -3,13 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.analysis.type;
 
-import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
-import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.fromDexType;
 
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.IRCode;
@@ -57,10 +53,10 @@
     }
   }
 
-  public void widening(DexEncodedMethod context, DexEncodedMethod encodedMethod, IRCode code) {
+  public void widening(IRCode code) {
     mode = Mode.WIDENING;
     assert worklist.isEmpty();
-    code.topologicallySortedBlocks().forEach(b -> analyzeBasicBlock(context, encodedMethod, b));
+    code.topologicallySortedBlocks().forEach(this::analyzeBasicBlock);
     analyze();
   }
 
@@ -95,31 +91,14 @@
     }
   }
 
-  private void analyzeBasicBlock(
-      DexEncodedMethod context, DexEncodedMethod encodedMethod, BasicBlock block) {
-    int argumentsSeen = encodedMethod.accessFlags.isStatic() ? 0 : -1;
+  private void analyzeBasicBlock(BasicBlock block) {
     for (Instruction instruction : block.getInstructions()) {
       Value outValue = instruction.outValue();
       if (outValue == null) {
         continue;
       }
-      // The type for Argument, a quasi instruction, can be inferred from the method signature.
       if (instruction.isArgument()) {
-        TypeLatticeElement derived;
-        if (argumentsSeen < 0) {
-          // Receiver
-          derived =
-              fromDexType(
-                  encodedMethod.method.holder,
-                  // Now we try inlining even when the receiver could be null.
-                  encodedMethod == context ? definitelyNotNull() : maybeNull(),
-                  appView);
-        } else {
-          DexType argType = encodedMethod.method.proto.parameters.values[argumentsSeen];
-          derived = fromDexType(argType, maybeNull(), appView);
-        }
-        argumentsSeen++;
-        updateTypeOfValue(outValue, derived);
+        // The type for Argument, a quasi instruction is already set correctly during IR building.
         // Note that we don't need to enqueue the out value of arguments here because it's constant.
       } else if (instruction.hasInvariantOutType()) {
         TypeLatticeElement derived = instruction.evaluate(appView);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index 7624412..bdba162 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
@@ -83,14 +84,16 @@
     if (!isInvokeMethodWithDynamicDispatch() || !appView.appInfo().hasLiveness()) {
       return null;
     }
-    Collection<DexEncodedMethod> targets =
+    LookupResultSuccess lookupResult =
         appView
             .appInfo()
             .resolveMethod(method.holder, method)
-            .lookupVirtualDispatchTargets(appView.appInfo());
-    if (targets == null) {
+            .lookupVirtualDispatchTargets(appView.withLiveness())
+            .asLookupResultSuccess();
+    if (lookupResult == null) {
       return null;
     }
+    assert lookupResult.getMethodTargets() != null;
     DexType staticReceiverType = getInvokedMethod().holder;
     DexType refinedReceiverType =
         TypeAnalysis.getRefinedReceiverType(
@@ -103,7 +106,7 @@
       if (refinedResolution.isSingleResolution()) {
         DexEncodedMethod refinedTarget = refinedResolution.getSingleTarget();
         Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
-        for (DexEncodedMethod target : targets) {
+        for (DexEncodedMethod target : lookupResult.getMethodTargets()) {
           if (target == refinedTarget
               || appView.isSubtype(target.method.holder, refinedReceiverType).isPossiblyTrue()) {
             result.add(target);
@@ -113,7 +116,7 @@
       }
       // If resolution at the refined type fails, conservatively return the full set of targets.
     }
-    return targets;
+    return lookupResult.getMethodTargets();
   }
 
   public abstract InlineAction computeInlining(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index e1d3d75..6ba4a3a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -112,7 +112,8 @@
     }
     // Allow optimizing static library invokes in D8.
     DexClass clazz = appView.definitionFor(getInvokedMethod().holder);
-    if (clazz != null && clazz.isLibraryClass()) {
+    if (clazz != null
+        && (clazz.isLibraryClass() || appView.libraryMethodOptimizer().isModeled(clazz.type))) {
       return appView.definitionFor(getInvokedMethod());
     }
     // In D8, we can treat invoke-static instructions as having a single target if the invoke is
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index bdc7ce4..e1f67a9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -105,7 +105,8 @@
     DexType holder = getInvokedMethod().holder;
     if (holder.isClassType()) {
       DexClass clazz = appView.definitionFor(holder);
-      if (clazz != null && clazz.isLibraryClass()) {
+      if (clazz != null
+          && (clazz.isLibraryClass() || appView.libraryMethodOptimizer().isModeled(clazz.type))) {
         DexEncodedMethod singleTargetCandidate = appView.definitionFor(getInvokedMethod());
         if (singleTargetCandidate != null && (clazz.isFinal() || singleTargetCandidate.isFinal())) {
           return singleTargetCandidate;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
index 610240e..56462db 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.graph.FieldAccessInfo;
 import com.android.tools.r8.graph.FieldAccessInfoCollection;
 import com.android.tools.r8.graph.GraphLense.GraphLenseLookupResult;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.Invoke;
@@ -212,7 +213,11 @@
                 ResolutionResult resolution =
                     appView.appInfo().resolveMethod(method.holder, method, isInterface);
                 if (resolution.isVirtualTarget()) {
-                  return resolution.lookupVirtualDispatchTargets(appView.appInfo());
+                  LookupResult lookupResult =
+                      resolution.lookupVirtualDispatchTargets(appView, appView.appInfo());
+                  if (lookupResult.isLookupResultSuccess()) {
+                    return lookupResult.asLookupResultSuccess().getMethodTargets();
+                  }
                 }
                 return null;
               });
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 3d0fed3..a39a66b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -619,9 +619,9 @@
     if (hasImpreciseValues || impreciseInstructions != null) {
       // In DEX we may need to constrain all values and instructions to precise types.
       assert source instanceof DexSourceCode;
-      new TypeConstraintResolver(appView, this).resolve(impreciseInstructions, ir, method, context);
+      new TypeConstraintResolver(appView, this).resolve(impreciseInstructions, ir);
     } else {
-      new TypeAnalysis(appView).widening(context, method, ir);
+      new TypeAnalysis(appView).widening(ir);
     }
 
     // Update the IR code if collected call site optimization info has something useful.
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index b1b6e81..94df8fb 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -27,7 +27,8 @@
 import com.android.tools.r8.ir.analysis.TypeChecker;
 import com.android.tools.r8.ir.analysis.constant.SparseConditionalConstantPropagation;
 import com.android.tools.r8.ir.analysis.fieldaccess.FieldAccessAnalysis;
-import com.android.tools.r8.ir.analysis.fieldvalueanalysis.FieldValueAnalysis;
+import com.android.tools.r8.ir.analysis.fieldvalueanalysis.InstanceFieldValueAnalysis;
+import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValueAnalysis;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.AlwaysMaterializingDefinition;
 import com.android.tools.r8.ir.code.AlwaysMaterializingUser;
@@ -77,7 +78,6 @@
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
 import com.android.tools.r8.ir.optimize.lambda.LambdaMerger;
-import com.android.tools.r8.ir.optimize.library.LibraryMethodOptimizer;
 import com.android.tools.r8.ir.optimize.staticizer.ClassStaticizer;
 import com.android.tools.r8.ir.optimize.string.StringBuilderOptimizer;
 import com.android.tools.r8.ir.optimize.string.StringOptimizer;
@@ -129,7 +129,6 @@
   private final Outliner outliner;
   private final ClassInitializerDefaultsOptimization classInitializerDefaultsOptimization;
   private final FieldAccessAnalysis fieldAccessAnalysis;
-  private final LibraryMethodOptimizer libraryMethodOptimizer;
   private final LibraryMethodOverrideAnalysis libraryMethodOverrideAnalysis;
   private final StringConcatRewriter stringConcatRewriter;
   private final StringOptimizer stringOptimizer;
@@ -234,7 +233,6 @@
       this.classInliner = null;
       this.classStaticizer = null;
       this.fieldAccessAnalysis = null;
-      this.libraryMethodOptimizer = null;
       this.libraryMethodOverrideAnalysis = null;
       this.inliner = null;
       this.outliner = null;
@@ -268,7 +266,6 @@
         options.processCovariantReturnTypeAnnotations
             ? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
             : null;
-    this.libraryMethodOptimizer = new LibraryMethodOptimizer(appView);
     if (options.testing.forceAssumeNoneInsertion) {
       assumers.add(new AliasIntroducer(appView));
     }
@@ -510,9 +507,9 @@
   }
 
   private void clearSynthesizedClassMapping(Builder<?> builder) {
-    for (DexProgramClass programClass : builder.getProgramClasses()) {
-      programClass.annotations =
-          programClass.annotations.getWithout(builder.dexItemFactory.annotationSynthesizedClassMap);
+    for (DexProgramClass clazz : builder.getProgramClasses()) {
+      clazz.setAnnotations(
+          clazz.annotations().getWithout(builder.dexItemFactory.annotationSynthesizedClassMap));
     }
   }
 
@@ -542,7 +539,7 @@
       DexAnnotation updatedAnnotation =
           DexAnnotation.createAnnotationSynthesizedClassMap(synthesized, builder.dexItemFactory);
 
-      original.annotations = original.annotations.getWithAddedOrReplaced(updatedAnnotation);
+      original.setAnnotations(original.annotations().getWithAddedOrReplaced(updatedAnnotation));
     }
   }
 
@@ -1230,11 +1227,9 @@
       stringOptimizer.computeTrivialOperationsOnConstString(code);
       stringOptimizer.removeTrivialConversions(code);
       timing.end();
-      if (libraryMethodOptimizer != null) {
-        timing.begin("Optimize library methods");
-        libraryMethodOptimizer.optimize(code, feedback, methodProcessor);
-        timing.end();
-      }
+      timing.begin("Optimize library methods");
+      appView.libraryMethodOptimizer().optimize(code, feedback, methodProcessor);
+      timing.end();
       assert code.isConsistentSSA();
     }
 
@@ -1570,7 +1565,16 @@
 
     methodOptimizationInfoCollector
         .collectMethodOptimizationInfo(code.method, code, feedback, dynamicTypeOptimization);
-    FieldValueAnalysis.run(appView, code, classInitializerDefaultsResult, feedback, code.method);
+
+    if (method.isInitializer()) {
+      if (method.isClassInitializer()) {
+        StaticFieldValueAnalysis.run(
+            appView, code, classInitializerDefaultsResult, feedback, code.method);
+      } else {
+        InstanceFieldValueAnalysis.run(
+            appView, code, classInitializerDefaultsResult, feedback, code.method);
+      }
+    }
   }
 
   public void removeDeadCodeAndFinalizeIR(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
index 2c41a2a..7257d49 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
@@ -92,16 +91,12 @@
     }
   }
 
-  public void resolve(
-      List<ImpreciseMemberTypeInstruction> impreciseInstructions,
-      IRCode code,
-      DexEncodedMethod method,
-      DexEncodedMethod context) {
+  public void resolve(List<ImpreciseMemberTypeInstruction> impreciseInstructions, IRCode code) {
     // Round one will resolve at least all object vs single types.
     List<Value> remainingImpreciseValues = resolveRoundOne(code);
     // Round two will resolve any remaining single and wide types. These can depend on the types
     // of array instructions, thus we need to complete the type fixed point prior to resolving.
-    new TypeAnalysis(appView, true).widening(context, method, code);
+    new TypeAnalysis(appView, true).widening(code);
     // Round two resolves any remaining imprecision and finally selects a final precise type for
     // any unconstrained imprecise type.
     resolveRoundTwo(code, impreciseInstructions, remainingImpreciseValues);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 6ff25d9..fd0e452 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -527,6 +527,19 @@
     return rewritableMethods.getProvider(original);
   }
 
+  public static void checkForAssumedLibraryTypes(AppView<?> appView) {
+    Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+        appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
+    for (DexString methodName : retargetCoreLibMember.keySet()) {
+      for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+        DexClass typeClass = appView.definitionFor(inType);
+        if (typeClass == null) {
+          RewritableMethods.warnMissingRetargetCoreLibraryMember(inType, appView);
+        }
+      }
+    }
+  }
+
   private static final class RewritableMethods {
 
     // Map backported method to a provider for creating the actual target method (with code).
@@ -1574,9 +1587,9 @@
       DexType[] consumerTypes =
           new DexType[]{
               factory.consumerType,
-              factory.createType("Ljava/util/function/DoubleConsumer;"),
-              factory.createType("Ljava/util/function/LongConsumer;"),
-              factory.createType("Ljava/util/function/IntConsumer;")
+              factory.doubleConsumer,
+              factory.longConsumer,
+              factory.intConsumer
           };
       TemplateMethodFactory[] methodFactories =
           new TemplateMethodFactory[]{
@@ -1666,7 +1679,7 @@
               method, BackportedMethods::StreamMethods_ofNullable, "ofNullable"));
     }
 
-    private void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
+    private static void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
       StringDiagnostic warning =
           new StringDiagnostic(
               "Cannot retarget core library member "
@@ -1683,9 +1696,7 @@
       for (DexString methodName : retargetCoreLibMember.keySet()) {
         for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
           DexClass typeClass = appView.definitionFor(inType);
-          if (typeClass == null) {
-            warnMissingRetargetCoreLibraryMember(inType, appView);
-          } else {
+          if (typeClass != null) {
             DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
             List<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass);
             for (DexEncodedMethod encodedMethod : found) {
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 a0fb1c8..3cadabf 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
@@ -92,8 +92,8 @@
     }
     // Remove the CovariantReturnType annotations.
     for (DexEncodedMethod method : methodsWithCovariantReturnTypeAnnotation) {
-      method.annotations =
-          method.annotations.keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation));
+      method.setAnnotations(
+          method.annotations().keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)));
     }
     // Add the newly constructed methods to the class.
     clazz.appendVirtualMethods(covariantReturnTypeMethods);
@@ -115,7 +115,7 @@
   }
 
   private boolean methodHasCovariantReturnTypeAnnotation(DexEncodedMethod method) {
-    for (DexAnnotation annotation : method.annotations.annotations) {
+    for (DexAnnotation annotation : method.annotations().annotations) {
       if (isCovariantReturnTypeAnnotation(annotation.annotation)) {
         return true;
       }
@@ -162,7 +162,7 @@
         new DexEncodedMethod(
             newMethod,
             newAccessFlags,
-            method.annotations.keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)),
+            method.annotations().keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)),
             method.parameterAnnotationsList.keepIf(Predicates.alwaysTrue()),
             new SynthesizedCode(forwardSourceCodeBuilder::build),
             true);
@@ -181,7 +181,7 @@
   // then this method returns the set { SubOfFoo, SubOfSubOfFoo }.
   private Set<DexType> getCovariantReturnTypes(DexClass clazz, DexEncodedMethod method) {
     Set<DexType> covariantReturnTypes = new HashSet<>();
-    for (DexAnnotation annotation : method.annotations.annotations) {
+    for (DexAnnotation annotation : method.annotations().annotations) {
       if (isCovariantReturnTypeAnnotation(annotation.annotation)) {
         getCovariantReturnTypesFromAnnotation(
             clazz, method, annotation.annotation, covariantReturnTypes);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 04ce705..4409c30 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -94,8 +94,14 @@
         newFlags.promoteToStatic();
         DexEncodedMethod.setDebugInfoWithFakeThisParameter(
             code, companionMethod.getArity(), appView);
-        DexEncodedMethod implMethod = new DexEncodedMethod(
-            companionMethod, newFlags, virtual.annotations, virtual.parameterAnnotationsList, code, true);
+        DexEncodedMethod implMethod =
+            new DexEncodedMethod(
+                companionMethod,
+                newFlags,
+                virtual.annotations(),
+                virtual.parameterAnnotationsList,
+                code,
+                true);
         implMethod.copyMetadata(virtual);
         virtual.setDefaultInterfaceMethodImplementation(implMethod);
         companionMethods.add(implMethod);
@@ -129,12 +135,11 @@
             : "Static interface method " + direct.toSourceString() + " is expected to "
             + "either be public or private in " + iface.origin;
         DexMethod companionMethod = rewriter.staticAsMethodOfCompanionClass(oldMethod);
-        Code code = direct.getCode();
         DexEncodedMethod implMethod =
             new DexEncodedMethod(
                 companionMethod,
                 newFlags,
-                direct.annotations,
+                direct.annotations(),
                 direct.parameterAnnotationsList,
                 direct.getCode(),
                 true);
@@ -161,7 +166,7 @@
               new DexEncodedMethod(
                   companionMethod,
                   newFlags,
-                  direct.annotations,
+                  direct.annotations(),
                   direct.parameterAnnotationsList,
                   code,
                   true);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 330d72a..fae9325 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -631,7 +631,7 @@
               new DexEncodedMethod(
                   callTarget,
                   newAccessFlags,
-                  encodedMethod.annotations,
+                  encodedMethod.annotations(),
                   encodedMethod.parameterAnnotationsList,
                   encodedMethod.getCode(),
                   true);
@@ -686,7 +686,7 @@
               new DexEncodedMethod(
                   callTarget,
                   newAccessFlags,
-                  encodedMethod.annotations,
+                  encodedMethod.annotations(),
                   encodedMethod.parameterAnnotationsList,
                   encodedMethod.getCode(),
                   true);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index 02cb581..0546e9d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -204,8 +204,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/CharSequence;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 true),
             new CfStore(ValueType.INT, 2),
@@ -214,8 +214,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/CharSequence;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 true),
             new CfStore(ValueType.INT, 3),
@@ -235,11 +235,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.intType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("min")),
                 false),
             new CfStore(ValueType.INT, 5),
@@ -253,9 +253,9 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/CharSequence;"),
+                    options.itemFactory.charSequenceType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+                        options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
                 true),
             new CfStore(ValueType.INT, 6),
@@ -265,9 +265,9 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/CharSequence;"),
+                    options.itemFactory.charSequenceType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+                        options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
                 true),
             new CfStore(ValueType.INT, 7),
@@ -321,23 +321,23 @@
         1,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/lang/String;")),
+            new CfNew(options.itemFactory.stringType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("[C"), options.itemFactory.createType("I")),
+                        options.itemFactory.charArrayType, options.itemFactory.intType),
                     options.itemFactory.createString("toChars")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("[C")),
+                        options.itemFactory.voidType, options.itemFactory.charArrayType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -373,16 +373,16 @@
         ImmutableList.of(
             label0,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("Ljava/lang/AutoCloseable;")),
+            new CfInstanceOf(options.itemFactory.autoCloseableType),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("Ljava/lang/AutoCloseable;")),
+            new CfCheckCast(options.itemFactory.autoCloseableType),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/AutoCloseable;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.autoCloseableType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("close")),
                 true),
             new CfGoto(label11),
@@ -391,22 +391,21 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Class;")),
+                    options.itemFactory.objectType,
+                    options.itemFactory.createProto(options.itemFactory.classType),
                     options.itemFactory.createString("getClass")),
                 false),
             new CfConstString(options.itemFactory.createString("close")),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Class;")),
+            new CfNewArray(options.itemFactory.createSynthesizedType("[Ljava/lang/Class;")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Class;"),
+                    options.itemFactory.classType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("[Ljava/lang/Class;")),
+                        options.itemFactory.createSynthesizedType("Ljava/lang/reflect/Method;"),
+                        options.itemFactory.stringType,
+                        options.itemFactory.createSynthesizedType("[Ljava/lang/Class;")),
                     options.itemFactory.createString("getMethod")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
@@ -414,15 +413,15 @@
             new CfLoad(ValueType.OBJECT, 2),
             new CfLoad(ValueType.OBJECT, 1),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfNewArray(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/Method;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/reflect/Method;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
                     options.itemFactory.createString("invoke")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -431,124 +430,116 @@
             label5,
             new CfStore(ValueType.OBJECT, 2),
             label6,
-            new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Class;")),
+                    options.itemFactory.objectType,
+                    options.itemFactory.createProto(options.itemFactory.classType),
                     options.itemFactory.createString("getClass")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(" does not have a close() method.")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/AssertionError;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("Ljava/lang/Throwable;")),
+                        options.itemFactory.voidType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.throwableType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
             label7,
             new CfStore(ValueType.OBJECT, 2),
             label8,
-            new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("Fail to call close() on ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Class;")),
+                    options.itemFactory.objectType,
+                    options.itemFactory.createProto(options.itemFactory.classType),
                     options.itemFactory.createString("getClass")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/AssertionError;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("Ljava/lang/Throwable;")),
+                        options.itemFactory.voidType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.throwableType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -559,9 +550,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/InvocationTargetException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Throwable;")),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/reflect/InvocationTargetException;"),
+                    options.itemFactory.createProto(options.itemFactory.throwableType),
                     options.itemFactory.createString("getCause")),
                 false),
             new CfThrow(),
@@ -586,42 +577,46 @@
                 label2,
                 label4,
                 ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/NoSuchMethodException;")),
-                ImmutableList.of(label5)),
-            new CfTryCatch(
-                label2,
-                label4,
-                ImmutableList.of(options.itemFactory.createType("Ljava/lang/SecurityException;")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NoSuchMethodException;")),
                 ImmutableList.of(label5)),
             new CfTryCatch(
                 label2,
                 label4,
                 ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/IllegalAccessException;")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/SecurityException;")),
+                ImmutableList.of(label5)),
+            new CfTryCatch(
+                label2,
+                label4,
+                ImmutableList.of(
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IllegalAccessException;")),
                 ImmutableList.of(label7)),
             new CfTryCatch(
                 label2,
                 label4,
                 ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IllegalArgumentException;")),
                 ImmutableList.of(label7)),
             new CfTryCatch(
                 label2,
                 label4,
                 ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/ExceptionInInitializerError;")),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/ExceptionInInitializerError;")),
                 ImmutableList.of(label7)),
             new CfTryCatch(
                 label2,
                 label4,
                 ImmutableList.of(
-                    options.itemFactory.createType(
+                    options.itemFactory.createSynthesizedType(
                         "Ljava/lang/reflect/InvocationTargetException;")),
                 ImmutableList.of(label9)),
             new CfTryCatch(
                 label0,
                 label11,
-                ImmutableList.of(options.itemFactory.createType("Ljava/lang/Throwable;")),
+                ImmutableList.of(options.itemFactory.throwableType),
                 ImmutableList.of(label12))),
         ImmutableList.of());
   }
@@ -640,16 +635,16 @@
         6,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/ArrayList;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfArrayLength(),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
@@ -675,19 +670,17 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.booleanType, options.itemFactory.objectType),
                     options.itemFactory.createString("add")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -699,10 +692,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;"),
-                        options.itemFactory.createType("Ljava/util/List;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;")),
                     options.itemFactory.createString("unmodifiableList")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -724,17 +717,17 @@
         ImmutableList.of(
             label0,
             new CfNew(
-                options.itemFactory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;")),
+                options.itemFactory.createSynthesizedType(
+                    "Ljava/util/AbstractMap$SimpleImmutableEntry;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             label1,
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
@@ -742,20 +735,20 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/util/AbstractMap$SimpleImmutableEntry;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.voidType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType),
                     options.itemFactory.createString("<init>")),
                 false),
             label3,
@@ -782,16 +775,16 @@
         8,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashMap;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashMap;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfArrayLength(),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
@@ -816,18 +809,16 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("getKey")),
                 true),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfStore(ValueType.OBJECT, 6),
@@ -836,18 +827,16 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("getValue")),
                 true),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfStore(ValueType.OBJECT, 7),
@@ -858,61 +847,59 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType),
                     options.itemFactory.createString("put")),
                 false),
             new CfIf(If.Type.EQ, ValueType.OBJECT, label7),
             label6,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/IllegalArgumentException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("duplicate key: ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 6),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IllegalArgumentException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -924,10 +911,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Map;"),
-                        options.itemFactory.createType("Ljava/util/Map;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Map;")),
                     options.itemFactory.createString("unmodifiableMap")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -951,16 +938,16 @@
         6,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashSet;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashSet;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfArrayLength(),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
@@ -986,69 +973,65 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.booleanType, options.itemFactory.objectType),
                     options.itemFactory.createString("add")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label5),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/IllegalArgumentException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("duplicate element: ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IllegalArgumentException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -1060,10 +1043,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Set;"),
-                        options.itemFactory.createType("Ljava/util/Set;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Set;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Set;")),
                     options.itemFactory.createString("unmodifiableSet")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -1086,22 +1069,22 @@
         4,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/ArrayList;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("size")),
                 true),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
@@ -1110,9 +1093,9 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
                     options.itemFactory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
@@ -1121,8 +1104,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label5),
@@ -1130,9 +1113,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("next")),
                 true),
             new CfStore(ValueType.OBJECT, 3),
@@ -1142,19 +1124,17 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.booleanType, options.itemFactory.objectType),
                     options.itemFactory.createString("add")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -1165,10 +1145,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;"),
-                        options.itemFactory.createType("Ljava/util/List;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;")),
                     options.itemFactory.createString("unmodifiableList")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -1194,22 +1174,22 @@
         4,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashMap;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashMap;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("size")),
                 true),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
@@ -1218,17 +1198,17 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Set;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Set;")),
                     options.itemFactory.createString("entrySet")),
                 true),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Set;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Set;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
                     options.itemFactory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
@@ -1237,8 +1217,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -1246,12 +1226,11 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("next")),
                 true),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/Map$Entry;")),
+            new CfCheckCast(options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;")),
             new CfStore(ValueType.OBJECT, 3),
             label3,
             new CfLoad(ValueType.OBJECT, 1),
@@ -1260,18 +1239,16 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("getKey")),
                 true),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfLoad(ValueType.OBJECT, 3),
@@ -1279,29 +1256,27 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("getValue")),
                 true),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             label6,
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType),
                     options.itemFactory.createString("put")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -1312,10 +1287,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Map;"),
-                        options.itemFactory.createType("Ljava/util/Map;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Map;")),
                     options.itemFactory.createString("unmodifiableMap")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -1338,22 +1313,22 @@
         4,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashSet;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashSet;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("size")),
                 true),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
@@ -1362,9 +1337,9 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
                     options.itemFactory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
@@ -1373,8 +1348,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label5),
@@ -1382,9 +1357,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("next")),
                 true),
             new CfStore(ValueType.OBJECT, 3),
@@ -1394,19 +1368,17 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.booleanType, options.itemFactory.objectType),
                     options.itemFactory.createString("add")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -1417,10 +1389,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Set;"),
-                        options.itemFactory.createType("Ljava/util/Set;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Set;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Set;")),
                     options.itemFactory.createString("unmodifiableSet")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -1441,18 +1413,18 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;")),
                     options.itemFactory.createString("emptyList")),
                 false),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Enumeration;"),
-                        options.itemFactory.createType("Ljava/util/Collection;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Enumeration;"),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Collection;")),
                     options.itemFactory.createString("enumeration")),
                 false),
             new CfReturn(ValueType.OBJECT)),
@@ -1471,17 +1443,17 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;")),
                     options.itemFactory.createString("emptyList")),
                 false),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/List;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/List;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
                     options.itemFactory.createString("iterator")),
                 true),
             new CfReturn(ValueType.OBJECT)),
@@ -1501,17 +1473,17 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/List;")),
                     options.itemFactory.createString("emptyList")),
                 false),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/List;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/List;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/ListIterator;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/ListIterator;")),
                     options.itemFactory.createString("listIterator")),
                 true),
             new CfReturn(ValueType.OBJECT)),
@@ -1533,9 +1505,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Double;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Double;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"), options.itemFactory.createType("D")),
+                        options.itemFactory.longType, options.itemFactory.doubleType),
                     options.itemFactory.createString("doubleToLongBits")),
                 false),
             new CfStore(ValueType.LONG, 2),
@@ -1567,9 +1539,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Double;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Double;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("D")),
+                        options.itemFactory.booleanType, options.itemFactory.doubleType),
                     options.itemFactory.createString("isInfinite")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1577,9 +1549,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Double;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Double;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("D")),
+                        options.itemFactory.booleanType, options.itemFactory.doubleType),
                     options.itemFactory.createString("isNaN")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1609,9 +1581,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Float;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Float;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("F")),
+                        options.itemFactory.booleanType, options.itemFactory.floatType),
                     options.itemFactory.createString("isInfinite")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1619,9 +1591,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Float;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Float;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("F")),
+                        options.itemFactory.booleanType, options.itemFactory.floatType),
                     options.itemFactory.createString("isNaN")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1694,11 +1666,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.intType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("compare")),
                 false),
             new CfReturn(ValueType.INT),
@@ -1754,11 +1726,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.intType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("parseUnsignedInt")),
                 false),
             new CfReturn(ValueType.INT),
@@ -1786,8 +1758,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfConstNumber(1, ValueType.INT),
@@ -1797,9 +1769,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+                        options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
                 false),
             new CfConstNumber(43, ValueType.INT),
@@ -1810,10 +1782,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType, options.itemFactory.intType),
                     options.itemFactory.createString("substring")),
                 false),
             new CfStore(ValueType.OBJECT, 0),
@@ -1823,11 +1794,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.longType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("parseLong")),
                 false),
             new CfStore(ValueType.LONG, 2),
@@ -1839,55 +1810,52 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.EQ, ValueType.INT, label5),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("Input ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(" in base ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(
@@ -1895,27 +1863,24 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -1994,11 +1959,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("toUnsignedString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -2029,11 +1994,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.longType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -2068,11 +2033,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.intType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("compare")),
                 false),
             new CfReturn(ValueType.INT),
@@ -2219,11 +2184,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.longType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("parseUnsignedLong")),
                 false),
             new CfReturn(ValueType.LONG),
@@ -2266,8 +2231,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
@@ -2275,16 +2240,16 @@
             new CfLoad(ValueType.INT, 2),
             new CfIf(If.Type.NE, ValueType.INT, label3),
             label2,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstString(options.itemFactory.createString("empty string")),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -2296,35 +2261,33 @@
             new CfConstNumber(36, ValueType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label5),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstString(options.itemFactory.createString("illegal radix: ")),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType, options.itemFactory.intType),
                     options.itemFactory.createString("valueOf")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringType, options.itemFactory.stringType),
                     options.itemFactory.createString("concat")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -2335,11 +2298,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.longType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("divideUnsigned")),
                 false),
             new CfStore(ValueType.LONG, 3),
@@ -2349,9 +2312,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+                        options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
                 false),
             new CfConstNumber(43, ValueType.INT),
@@ -2381,20 +2344,20 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+                        options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("C"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.intType,
+                        options.itemFactory.charType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("digit")),
                 false),
             new CfStore(ValueType.INT, 9),
@@ -2403,16 +2366,16 @@
             new CfConstNumber(-1, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label15),
             label14,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -2437,36 +2400,35 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.longType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("remainderUnsigned")),
                 false),
             new CfNumberConversion(NumericType.LONG, NumericType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label18),
             label17,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstString(options.itemFactory.createString("Too large for unsigned long: ")),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringType, options.itemFactory.stringType),
                     options.itemFactory.createString("concat")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -2608,11 +2570,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.longType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("toUnsignedString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -2674,11 +2636,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.longType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -2694,7 +2656,7 @@
             new CfStore(ValueType.INT, 2),
             label6,
             new CfConstNumber(64, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[C")),
+            new CfNewArray(options.itemFactory.charArrayType),
             new CfStore(ValueType.OBJECT, 3),
             label7,
             new CfLoad(ValueType.OBJECT, 3),
@@ -2712,9 +2674,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("numberOfTrailingZeros")),
                 false),
             new CfStore(ValueType.INT, 5),
@@ -2735,11 +2697,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.charType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("forDigit")),
                 false),
             new CfArrayStore(MemberType.CHAR),
@@ -2779,11 +2741,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.longType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("divideUnsigned")),
                 false),
             new CfStore(ValueType.LONG, 5),
@@ -2805,11 +2767,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.charType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("forDigit")),
                 false),
             new CfArrayStore(MemberType.CHAR),
@@ -2834,11 +2796,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("C"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.charType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("forDigit")),
                 false),
             new CfArrayStore(MemberType.CHAR),
@@ -2850,7 +2812,7 @@
             new CfStore(ValueType.LONG, 0),
             new CfGoto(label22),
             label25,
-            new CfNew(options.itemFactory.createType("Ljava/lang/String;")),
+            new CfNew(options.itemFactory.stringType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 3),
             new CfLoad(ValueType.INT, 4),
@@ -2861,12 +2823,12 @@
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("[C"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.voidType,
+                        options.itemFactory.charArrayType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -2908,13 +2870,13 @@
             new CfLoad(ValueType.INT, 4),
             new CfReturn(ValueType.INT),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -2972,13 +2934,13 @@
             new CfLoad(ValueType.LONG, 4),
             new CfReturn(ValueType.LONG),
             label7,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3002,13 +2964,13 @@
             new CfConstNumber(-2147483648, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3038,13 +3000,13 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3193,11 +3155,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.longType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("floorDiv")),
                 false),
             new CfReturn(ValueType.LONG),
@@ -3325,11 +3287,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.longType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("floorMod")),
                 false),
             new CfNumberConversion(NumericType.LONG, NumericType.INT),
@@ -3354,13 +3316,13 @@
             new CfConstNumber(2147483647, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3390,13 +3352,13 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3443,13 +3405,13 @@
             new CfLoad(ValueType.INT, 4),
             new CfReturn(ValueType.INT),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3487,9 +3449,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+                        options.itemFactory.intType, options.itemFactory.longType),
                     options.itemFactory.createString("numberOfLeadingZeros")),
                 false),
             new CfLoad(ValueType.LONG, 0),
@@ -3499,9 +3461,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+                        options.itemFactory.intType, options.itemFactory.longType),
                     options.itemFactory.createString("numberOfLeadingZeros")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3510,9 +3472,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+                        options.itemFactory.intType, options.itemFactory.longType),
                     options.itemFactory.createString("numberOfLeadingZeros")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3523,9 +3485,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+                        options.itemFactory.intType, options.itemFactory.longType),
                     options.itemFactory.createString("numberOfLeadingZeros")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3583,13 +3545,13 @@
             new CfLoad(ValueType.LONG, 5),
             new CfReturn(ValueType.LONG),
             label15,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3613,11 +3575,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.longType,
+                        options.itemFactory.longType,
+                        options.itemFactory.longType),
                     options.itemFactory.createString("multiplyExact")),
                 false),
             new CfReturn(ValueType.LONG),
@@ -3765,13 +3727,13 @@
             new CfConstNumber(-2147483648, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3800,13 +3762,13 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3833,9 +3795,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("D"), options.itemFactory.createType("D")),
+                        options.itemFactory.doubleType, options.itemFactory.doubleType),
                     options.itemFactory.createString("nextUp")),
                 false),
             new CfNeg(NumericType.DOUBLE),
@@ -3859,9 +3821,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("F"), options.itemFactory.createType("F")),
+                        options.itemFactory.floatType, options.itemFactory.floatType),
                     options.itemFactory.createString("nextUp")),
                 false),
             new CfNeg(NumericType.FLOAT),
@@ -3904,13 +3866,13 @@
             new CfLoad(ValueType.INT, 4),
             new CfReturn(ValueType.INT),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -3968,13 +3930,13 @@
             new CfLoad(ValueType.LONG, 4),
             new CfReturn(ValueType.LONG),
             label7,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -4005,13 +3967,13 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.EQ, ValueType.INT, label3),
             label2,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -4047,112 +4009,104 @@
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/IndexOutOfBoundsException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("Range [")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(", ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(" + ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(") out of bounds for length ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IndexOutOfBoundsException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -4184,92 +4138,86 @@
             new CfLoad(ValueType.INT, 2),
             new CfIfCmp(If.Type.LE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/IndexOutOfBoundsException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("Range [")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(", ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(") out of bounds for length ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IndexOutOfBoundsException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -4298,72 +4246,68 @@
             new CfLoad(ValueType.INT, 1),
             new CfIfCmp(If.Type.LT, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/IndexOutOfBoundsException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("Index ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfConstString(options.itemFactory.createString(" out of bounds for length ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IndexOutOfBoundsException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -4398,11 +4342,11 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Comparator;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Comparator;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.intType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType),
                     options.itemFactory.createString("compare")),
                 true),
             label2,
@@ -4471,24 +4415,24 @@
             new CfReturn(ValueType.INT),
             label2,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[Z")),
+            new CfInstanceOf(options.itemFactory.booleanArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label6),
             label3,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[Z")),
+            new CfInstanceOf(options.itemFactory.booleanArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label4),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[Z")),
+            new CfCheckCast(options.itemFactory.booleanArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[Z")),
+            new CfCheckCast(options.itemFactory.booleanArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[Z"),
-                        options.itemFactory.createType("[Z")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.booleanArrayType,
+                        options.itemFactory.booleanArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label4),
@@ -4500,24 +4444,24 @@
             new CfReturn(ValueType.INT),
             label6,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[B")),
+            new CfInstanceOf(options.itemFactory.byteArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label10),
             label7,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[B")),
+            new CfInstanceOf(options.itemFactory.byteArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[B")),
+            new CfCheckCast(options.itemFactory.byteArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[B")),
+            new CfCheckCast(options.itemFactory.byteArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[B"),
-                        options.itemFactory.createType("[B")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.byteArrayType,
+                        options.itemFactory.byteArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -4529,24 +4473,24 @@
             new CfReturn(ValueType.INT),
             label10,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[C")),
+            new CfInstanceOf(options.itemFactory.charArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label14),
             label11,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[C")),
+            new CfInstanceOf(options.itemFactory.charArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label12),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[C")),
+            new CfCheckCast(options.itemFactory.charArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[C")),
+            new CfCheckCast(options.itemFactory.charArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[C"),
-                        options.itemFactory.createType("[C")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.charArrayType,
+                        options.itemFactory.charArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label12),
@@ -4558,24 +4502,24 @@
             new CfReturn(ValueType.INT),
             label14,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[D")),
+            new CfInstanceOf(options.itemFactory.doubleArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label18),
             label15,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[D")),
+            new CfInstanceOf(options.itemFactory.doubleArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label16),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[D")),
+            new CfCheckCast(options.itemFactory.doubleArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[D")),
+            new CfCheckCast(options.itemFactory.doubleArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[D"),
-                        options.itemFactory.createType("[D")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.doubleArrayType,
+                        options.itemFactory.doubleArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label16),
@@ -4587,24 +4531,24 @@
             new CfReturn(ValueType.INT),
             label18,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[F")),
+            new CfInstanceOf(options.itemFactory.floatArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label22),
             label19,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[F")),
+            new CfInstanceOf(options.itemFactory.floatArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label20),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[F")),
+            new CfCheckCast(options.itemFactory.floatArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[F")),
+            new CfCheckCast(options.itemFactory.floatArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[F"),
-                        options.itemFactory.createType("[F")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.floatArrayType,
+                        options.itemFactory.floatArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label20),
@@ -4616,24 +4560,24 @@
             new CfReturn(ValueType.INT),
             label22,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[I")),
+            new CfInstanceOf(options.itemFactory.intArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label26),
             label23,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[I")),
+            new CfInstanceOf(options.itemFactory.intArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label24),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[I")),
+            new CfCheckCast(options.itemFactory.intArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[I")),
+            new CfCheckCast(options.itemFactory.intArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[I"),
-                        options.itemFactory.createType("[I")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.intArrayType,
+                        options.itemFactory.intArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label24),
@@ -4645,24 +4589,24 @@
             new CfReturn(ValueType.INT),
             label26,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[J")),
+            new CfInstanceOf(options.itemFactory.longArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label30),
             label27,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[J")),
+            new CfInstanceOf(options.itemFactory.longArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label28),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[J")),
+            new CfCheckCast(options.itemFactory.longArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[J")),
+            new CfCheckCast(options.itemFactory.longArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[J"),
-                        options.itemFactory.createType("[J")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.longArrayType,
+                        options.itemFactory.longArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label28),
@@ -4674,24 +4618,24 @@
             new CfReturn(ValueType.INT),
             label30,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[S")),
+            new CfInstanceOf(options.itemFactory.shortArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label34),
             label31,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[S")),
+            new CfInstanceOf(options.itemFactory.shortArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label32),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[S")),
+            new CfCheckCast(options.itemFactory.shortArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[S")),
+            new CfCheckCast(options.itemFactory.shortArrayType),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[S"),
-                        options.itemFactory.createType("[S")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.shortArrayType,
+                        options.itemFactory.shortArrayType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label32),
@@ -4703,24 +4647,24 @@
             new CfReturn(ValueType.INT),
             label34,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfInstanceOf(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
             new CfIf(If.Type.EQ, ValueType.INT, label38),
             label35,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfInstanceOf(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
             new CfIf(If.Type.EQ, ValueType.INT, label36),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfCheckCast(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfCheckCast(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("[Ljava/lang/Object;"),
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
+                        options.itemFactory.booleanType,
+                        options.itemFactory.createSynthesizedType("[Ljava/lang/Object;"),
+                        options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
                     options.itemFactory.createString("deepEquals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label36),
@@ -4736,10 +4680,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
+                    options.itemFactory.objectType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.booleanType, options.itemFactory.objectType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfReturn(ValueType.INT),
@@ -4770,10 +4713,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
+                    options.itemFactory.objectType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.booleanType, options.itemFactory.objectType),
                     options.itemFactory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -4809,8 +4751,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.objectType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("hashCode")),
                 false),
             label2,
@@ -4889,11 +4831,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.stringType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -4924,20 +4866,20 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.stringType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/function/Supplier;")),
+            new CfCheckCast(
+                options.itemFactory.createSynthesizedType("Ljava/util/function/Supplier;")),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Supplier;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/function/Supplier;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("get")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
@@ -4947,11 +4889,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.objectType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.stringType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -4975,16 +4917,16 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -5010,11 +4952,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.objectType,
+                        options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -5043,9 +4985,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Object;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.objectType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             label2,
@@ -5071,8 +5012,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5082,18 +5023,16 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("get")),
                 false),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Consumer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/function/Consumer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.voidType, options.itemFactory.objectType),
                     options.itemFactory.createString("accept")),
                 true),
             new CfGoto(label3),
@@ -5102,8 +5041,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("run")),
                 true),
             label3,
@@ -5130,8 +5069,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5141,16 +5080,17 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("D")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+                    options.itemFactory.createProto(options.itemFactory.doubleType),
                     options.itemFactory.createString("getAsDouble")),
                 false),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/DoubleConsumer;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/util/function/DoubleConsumer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("D")),
+                        options.itemFactory.voidType, options.itemFactory.doubleType),
                     options.itemFactory.createString("accept")),
                 true),
             new CfGoto(label3),
@@ -5159,8 +5099,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("run")),
                 true),
             label3,
@@ -5187,8 +5127,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5198,16 +5138,16 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("getAsInt")),
                 false),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/IntConsumer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/function/IntConsumer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("accept")),
                 true),
             new CfGoto(label3),
@@ -5216,8 +5156,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("run")),
                 true),
             label3,
@@ -5244,8 +5184,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5255,16 +5195,16 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("J")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+                    options.itemFactory.createProto(options.itemFactory.longType),
                     options.itemFactory.createString("getAsLong")),
                 false),
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/LongConsumer;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/function/LongConsumer;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("J")),
+                        options.itemFactory.voidType, options.itemFactory.longType),
                     options.itemFactory.createString("accept")),
                 true),
             new CfGoto(label3),
@@ -5273,8 +5213,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("run")),
                 true),
             label3,
@@ -5299,8 +5239,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5330,8 +5270,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5361,8 +5301,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5392,8 +5332,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5425,10 +5365,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5437,8 +5376,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label3),
@@ -5450,25 +5389,23 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Supplier;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/function/Supplier;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("get")),
                 true),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/Optional;")),
+            new CfCheckCast(options.itemFactory.createSynthesizedType("Ljava/util/Optional;")),
             new CfStore(ValueType.OBJECT, 2),
             label4,
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.objectType, options.itemFactory.objectType),
                     options.itemFactory.createString("requireNonNull")),
                 false),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/Optional;")),
+            new CfCheckCast(options.itemFactory.createSynthesizedType("Ljava/util/Optional;")),
             new CfReturn(ValueType.OBJECT),
             label5),
         ImmutableList.of(),
@@ -5490,8 +5427,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5500,18 +5437,17 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("get")),
                 false),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
+                        options.itemFactory.objectType),
                     options.itemFactory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5519,9 +5455,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;")),
                     options.itemFactory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5545,8 +5481,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5555,17 +5491,18 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("D")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+                    options.itemFactory.createProto(options.itemFactory.doubleType),
                     options.itemFactory.createString("getAsDouble")),
                 false),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/DoubleStream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
-                        options.itemFactory.createType("D")),
+                        options.itemFactory.createSynthesizedType(
+                            "Ljava/util/stream/DoubleStream;"),
+                        options.itemFactory.doubleType),
                     options.itemFactory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5573,9 +5510,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/DoubleStream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/DoubleStream;")),
+                        options.itemFactory.createSynthesizedType(
+                            "Ljava/util/stream/DoubleStream;")),
                     options.itemFactory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5599,8 +5537,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5609,17 +5547,17 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("getAsInt")),
                 false),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/IntStream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/IntStream;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;"),
+                        options.itemFactory.intType),
                     options.itemFactory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5627,9 +5565,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/IntStream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/IntStream;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;")),
                     options.itemFactory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5653,8 +5591,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5663,17 +5601,17 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("J")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+                    options.itemFactory.createProto(options.itemFactory.longType),
                     options.itemFactory.createString("getAsLong")),
                 false),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/LongStream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/LongStream;"),
-                        options.itemFactory.createType("J")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;"),
+                        options.itemFactory.longType),
                     options.itemFactory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5681,9 +5619,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/LongStream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/LongStream;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;")),
                     options.itemFactory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
@@ -5785,9 +5723,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;")),
                     options.itemFactory.createString("empty")),
                 true),
             new CfGoto(label2),
@@ -5796,10 +5734,10 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
+                    options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
+                        options.itemFactory.objectType),
                     options.itemFactory.createString("of")),
                 true),
             label2,
@@ -5833,8 +5771,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
@@ -5848,9 +5786,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("codePointAt")),
                 false),
             new CfStore(ValueType.INT, 3),
@@ -5859,9 +5797,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+                        options.itemFactory.booleanType, options.itemFactory.intType),
                     options.itemFactory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label6),
@@ -5874,9 +5812,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -5911,27 +5849,27 @@
             label0,
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label1),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstString(options.itemFactory.createString("delimiter")),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
@@ -5947,10 +5885,10 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;")),
+                        options.itemFactory.stringBuilderType,
+                        options.itemFactory.charSequenceType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5968,10 +5906,10 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;")),
+                        options.itemFactory.stringBuilderType,
+                        options.itemFactory.charSequenceType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5983,10 +5921,10 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;")),
+                        options.itemFactory.stringBuilderType,
+                        options.itemFactory.charSequenceType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5998,9 +5936,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -6028,27 +5965,27 @@
             label0,
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label1),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstString(options.itemFactory.createString("delimiter")),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
@@ -6057,9 +5994,9 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Iterable;"),
+                    options.itemFactory.createSynthesizedType("Ljava/lang/Iterable;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
+                        options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
                     options.itemFactory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 3),
@@ -6068,8 +6005,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -6079,19 +6016,18 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("next")),
                 true),
-            new CfCheckCast(options.itemFactory.createType("Ljava/lang/CharSequence;")),
+            new CfCheckCast(options.itemFactory.charSequenceType),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;")),
+                        options.itemFactory.stringBuilderType,
+                        options.itemFactory.charSequenceType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6100,8 +6036,8 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("Z")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.booleanType),
                     options.itemFactory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -6111,10 +6047,10 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;")),
+                        options.itemFactory.stringBuilderType,
+                        options.itemFactory.charSequenceType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6124,19 +6060,18 @@
             new CfInvoke(
                 185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/Object;")),
+                    options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+                    options.itemFactory.createProto(options.itemFactory.objectType),
                     options.itemFactory.createString("next")),
                 true),
-            new CfCheckCast(options.itemFactory.createType("Ljava/lang/CharSequence;")),
+            new CfCheckCast(options.itemFactory.charSequenceType),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;")),
+                        options.itemFactory.stringBuilderType,
+                        options.itemFactory.charSequenceType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6146,9 +6081,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -6181,52 +6115,50 @@
             new CfLoad(ValueType.INT, 1),
             new CfIf(If.Type.GE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfNew(
+                options.itemFactory.createSynthesizedType("Ljava/lang/IllegalArgumentException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("V")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.voidType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfConstString(options.itemFactory.createString("count is negative: ")),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
                     options.itemFactory.createString("append")),
                 false),
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
+                    options.itemFactory.createSynthesizedType(
+                        "Ljava/lang/IllegalArgumentException;"),
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.voidType, options.itemFactory.stringType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfThrow(),
@@ -6235,8 +6167,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
@@ -6256,7 +6188,7 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfReturn(ValueType.OBJECT),
             label7,
-            new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+            new CfNew(options.itemFactory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.INT, 2),
             new CfLoad(ValueType.INT, 1),
@@ -6264,9 +6196,9 @@
             new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+                        options.itemFactory.voidType, options.itemFactory.intType),
                     options.itemFactory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 3),
@@ -6283,10 +6215,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+                    options.itemFactory.stringBuilderType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
                     options.itemFactory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6298,9 +6229,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/StringBuilder;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;")),
+                    options.itemFactory.stringBuilderType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
                     options.itemFactory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -6339,8 +6269,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
@@ -6354,9 +6284,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("codePointAt")),
                 false),
             new CfStore(ValueType.INT, 3),
@@ -6365,9 +6295,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+                        options.itemFactory.booleanType, options.itemFactory.intType),
                     options.itemFactory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label6),
@@ -6379,9 +6309,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -6398,11 +6328,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.intType,
+                        options.itemFactory.charSequenceType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("codePointBefore")),
                 false),
             new CfStore(ValueType.INT, 3),
@@ -6411,9 +6341,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+                        options.itemFactory.booleanType, options.itemFactory.intType),
                     options.itemFactory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label12),
@@ -6425,9 +6355,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -6441,11 +6371,11 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("substring")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -6478,8 +6408,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
@@ -6493,9 +6423,9 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("codePointAt")),
                 false),
             new CfStore(ValueType.INT, 3),
@@ -6504,9 +6434,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+                        options.itemFactory.booleanType, options.itemFactory.intType),
                     options.itemFactory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label6),
@@ -6518,9 +6448,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -6534,11 +6464,11 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("substring")),
                 false),
             new CfReturn(ValueType.OBJECT),
@@ -6567,8 +6497,8 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
-                    options.itemFactory.createProto(options.itemFactory.createType("I")),
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
                     options.itemFactory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 1),
@@ -6581,11 +6511,11 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("Ljava/lang/CharSequence;"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.intType,
+                        options.itemFactory.charSequenceType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("codePointBefore")),
                 false),
             new CfStore(ValueType.INT, 2),
@@ -6594,9 +6524,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+                        options.itemFactory.booleanType, options.itemFactory.intType),
                     options.itemFactory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label5),
@@ -6608,9 +6538,9 @@
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Character;"),
+                    options.itemFactory.boxedCharType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+                        options.itemFactory.intType, options.itemFactory.intType),
                     options.itemFactory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -6624,11 +6554,11 @@
             new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/String;"),
+                    options.itemFactory.stringType,
                     options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/String;"),
-                        options.itemFactory.createType("I"),
-                        options.itemFactory.createType("I")),
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
                     options.itemFactory.createString("substring")),
                 false),
             new CfReturn(ValueType.OBJECT),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
index 9e78a3b..ee175f9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
@@ -73,7 +73,7 @@
       InternalOptions options, DexMethod method, int formalCount) {
     DexType mapEntryArray =
         options.itemFactory.createArrayType(1, options.itemFactory.mapEntryType);
-    DexType simpleEntry = options.itemFactory.createType("Ljava/util/AbstractMap$SimpleEntry;");
+    DexType simpleEntry = options.itemFactory.abstractMapSimpleEntryType;
     DexMethod simpleEntryConstructor = options.itemFactory.createMethod(
         simpleEntry,
         options.itemFactory.createProto(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 55db2fd..5b695a7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -25,7 +25,6 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.equivalence.BasicBlockBehavioralSubsumption;
-import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -86,7 +85,6 @@
 import com.android.tools.r8.utils.SetUtils;
 import com.google.common.base.Equivalence;
 import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
@@ -131,6 +129,7 @@
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 public class CodeRewriter {
 
@@ -3113,7 +3112,7 @@
                       dexItemFactory.throwableMethods.initCause,
                       code.createValue(
                           TypeLatticeElement.fromDexType(
-                              dexItemFactory.throwableType, Nullability.maybeNull(), appView)),
+                              dexItemFactory.throwableType, maybeNull(), appView)),
                       initCauseArguments);
               initCause.setPosition(current.getPosition());
               insnIterator.add(initCause);
@@ -3352,8 +3351,8 @@
 
     // Now that the block is split there should not be any catch handlers in the block.
     assert !block.hasCatchHandlers();
-    DexType javaLangSystemType = dexItemFactory.createType("Ljava/lang/System;");
-    DexType javaIoPrintStreamType = dexItemFactory.createType("Ljava/io/PrintStream;");
+    DexType javaLangSystemType = dexItemFactory.javaLangSystemType;
+    DexType javaIoPrintStreamType = dexItemFactory.javaIoPrintStreamType;
     Value out =
         code.createValue(
             TypeLatticeElement.fromDexType(javaIoPrintStreamType, definitelyNotNull(), appView));
@@ -3583,13 +3582,6 @@
 
   // See comment for InternalOptions.canHaveNumberConversionRegisterAllocationBug().
   public void workaroundNumberConversionRegisterAllocationBug(IRCode code) {
-    final Supplier<DexMethod> javaLangDoubleisNaN = Suppliers.memoize(() ->
-     dexItemFactory.createMethod(
-        dexItemFactory.createString("Ljava/lang/Double;"),
-        dexItemFactory.createString("isNaN"),
-        dexItemFactory.booleanDescriptor,
-        new DexString[]{dexItemFactory.doubleDescriptor}));
-
     ListIterator<BasicBlock> blocks = code.listIterator();
     while (blocks.hasNext()) {
       BasicBlock block = blocks.next();
@@ -3607,7 +3599,8 @@
                 && value.definition.isNumberConversion()
                 && value.definition.asNumberConversion().to == NumericType.DOUBLE) {
               InvokeStatic invokeIsNaN =
-                  new InvokeStatic(javaLangDoubleisNaN.get(), null, ImmutableList.of(value));
+                  new InvokeStatic(
+                      dexItemFactory.doubleMethods.isNaN, null, ImmutableList.of(value));
               invokeIsNaN.setPosition(instruction.getPosition());
 
               // Insert the invoke before the current instruction.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index a4c70be..96819d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -15,13 +15,13 @@
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.ir.code.Invoke.Type;
 import com.android.tools.r8.ir.optimize.Inliner.Constraint;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.Collection;
 import java.util.function.BiFunction;
 
 // Computes the inlining constraint for a given instruction.
@@ -442,9 +442,11 @@
 
     // For each of the actual potential targets, derive constraints based on the accessibility
     // of the method itself.
-    Collection<DexEncodedMethod> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appView.appInfo());
-    for (DexEncodedMethod target : targets) {
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    if (lookupResult.isLookupResultFailure()) {
+      return ConstraintWithTarget.NEVER;
+    }
+    for (DexEncodedMethod target : lookupResult.asLookupResultSuccess().getMethodTargets()) {
       methodHolder = graphLense.lookupType(target.method.holder);
       assert appView.definitionFor(methodHolder) != null;
       methodConstraintWithTarget =
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
index cf4f72b..2c8e6b9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
@@ -73,7 +73,7 @@
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     switchMapPrefix = dexItemFactory.createString("$SwitchMap$");
     kotlinSwitchMapPrefix = dexItemFactory.createString("$EnumSwitchMapping$");
-    intArrayType = dexItemFactory.createType("[I");
+    intArrayType = dexItemFactory.intArrayType;
   }
 
   public AppInfoWithLiveness run() {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 8fee6c5..6512985 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -234,7 +234,9 @@
                 cls.hasKotlinInfo()
                     && cls.getKotlinInfo().isSyntheticClass()
                     && cls.getKotlinInfo().asSyntheticClass().isLambda()
-                    && KotlinLambdaGroupIdFactory.hasValidAnnotations(kotlin, cls))
+                    && KotlinLambdaGroupIdFactory.hasValidAnnotations(kotlin, cls)
+                    && (appView.options().featureSplitConfiguration == null
+                        || !appView.options().featureSplitConfiguration.isInFeature(cls)))
         .sorted((a, b) -> a.type.slowCompareTo(b.type)) // Ensure stable ordering.
         .forEachOrdered(
             lambda -> {
@@ -358,7 +360,7 @@
 
     // Rewrite lambda class references into lambda group class
     // references inside methods from the processing queue.
-    rewriteLambdaReferences(converter, executorService, feedback);
+    rewriteLambdaReferences(converter, executorService);
     this.mode = null;
 
     appView.setHorizontallyMergedLambdaClasses(
@@ -423,8 +425,7 @@
     }
   }
 
-  private void rewriteLambdaReferences(
-      IRConverter converter, ExecutorService executorService, OptimizationFeedback feedback)
+  private void rewriteLambdaReferences(IRConverter converter, ExecutorService executorService)
       throws ExecutionException {
     if (methodsToReprocess.isEmpty()) {
       return;
@@ -440,27 +441,22 @@
   private void analyzeClass(DexProgramClass clazz) {
     lambdaInvalidator.accept(clazz.superType);
     lambdaInvalidator.accept(clazz.interfaces);
-    lambdaInvalidator.accept(clazz.annotations);
+    lambdaInvalidator.accept(clazz.annotations());
 
     for (DexEncodedField field : clazz.staticFields()) {
-      lambdaInvalidator.accept(field.annotations);
+      lambdaInvalidator.accept(field.annotations());
       if (field.field.type != clazz.type) {
         // Ignore static fields of the same type.
         lambdaInvalidator.accept(field.field, clazz.type);
       }
     }
     for (DexEncodedField field : clazz.instanceFields()) {
-      lambdaInvalidator.accept(field.annotations);
+      lambdaInvalidator.accept(field.annotations());
       lambdaInvalidator.accept(field.field, clazz.type);
     }
 
-    for (DexEncodedMethod method : clazz.directMethods()) {
-      lambdaInvalidator.accept(method.annotations);
-      lambdaInvalidator.accept(method.parameterAnnotationsList);
-      lambdaInvalidator.accept(method.method, clazz.type);
-    }
-    for (DexEncodedMethod method : clazz.virtualMethods()) {
-      lambdaInvalidator.accept(method.annotations);
+    for (DexEncodedMethod method : clazz.methods()) {
+      lambdaInvalidator.accept(method.annotations());
       lambdaInvalidator.accept(method.parameterAnnotationsList);
       lambdaInvalidator.accept(method.method, clazz.type);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java
index 996099b..b1fabf6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java
@@ -60,7 +60,7 @@
     this.signature = signature;
     this.mainMethodName = mainMethod.method.name;
     this.mainMethodProto = mainMethod.method.proto;
-    this.mainMethodAnnotations = mainMethod.annotations;
+    this.mainMethodAnnotations = mainMethod.annotations();
     this.mainMethodParamAnnotations = mainMethod.parameterAnnotationsList;
     this.innerClassAccess = inner != null ? inner.getAccess() : MISSING_INNER_CLASS_ATTRIBUTE;
     this.enclosing = enclosing;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java
index 568a8cb..9344464 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java
@@ -87,40 +87,36 @@
   }
 
   public static boolean hasValidAnnotations(Kotlin kotlin, DexClass lambda) {
-    if (!lambda.annotations.isEmpty()) {
-      for (DexAnnotation annotation : lambda.annotations.annotations) {
-        if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
-          continue;
-        }
-        if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
-          continue;
-        }
-        return false;
+    for (DexAnnotation annotation : lambda.annotations().annotations) {
+      if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
+        continue;
       }
+      if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
+        continue;
+      }
+      return false;
     }
     return true;
   }
 
   String validateAnnotations(Kotlin kotlin, DexClass lambda) throws LambdaStructureError {
     String signature = null;
-    if (!lambda.annotations.isEmpty()) {
-      for (DexAnnotation annotation : lambda.annotations.annotations) {
-        if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
-          signature = DexAnnotation.getSignature(annotation);
-          continue;
-        }
-
-        if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
-          // Ignore kotlin metadata on lambda classes. Metadata on synthetic
-          // classes exists but is not used in the current Kotlin version (1.2.21)
-          // and newly generated lambda _group_ class is not exactly a kotlin class.
-          continue;
-        }
-
-        assert !hasValidAnnotations(kotlin, lambda);
-        throw new LambdaStructureError(
-            "unexpected annotation: " + annotation.annotation.type.toSourceString());
+    for (DexAnnotation annotation : lambda.annotations().annotations) {
+      if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
+        signature = DexAnnotation.getSignature(annotation);
+        continue;
       }
+
+      if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
+        // Ignore kotlin metadata on lambda classes. Metadata on synthetic
+        // classes exists but is not used in the current Kotlin version (1.2.21)
+        // and newly generated lambda _group_ class is not exactly a kotlin class.
+        continue;
+      }
+
+      assert !hasValidAnnotations(kotlin, lambda);
+      throw new LambdaStructureError(
+          "unexpected annotation: " + annotation.annotation.type.toSourceString());
     }
     assert hasValidAnnotations(kotlin, lambda);
     return signature;
@@ -206,21 +202,31 @@
     }
   }
 
-  void checkDirectMethodAnnotations(DexEncodedMethod method) throws LambdaStructureError {
-    if (!method.annotations.isEmpty()) {
-      throw new LambdaStructureError("unexpected method annotations [" +
-          method.annotations.toSmaliString() + "] on " + method.method.toSourceString());
+  private static void checkDirectMethodAnnotations(DexEncodedMethod method)
+      throws LambdaStructureError {
+    if (!method.annotations().isEmpty()) {
+      throw new LambdaStructureError(
+          "unexpected method annotations ["
+              + method.annotations().toSmaliString()
+              + "] on "
+              + method.method.toSourceString());
     }
     if (!method.parameterAnnotationsList.isEmpty()) {
-      throw new LambdaStructureError("unexpected method parameters annotations [" +
-          method.annotations.toSmaliString() + "] on " + method.method.toSourceString());
+      throw new LambdaStructureError(
+          "unexpected method parameters annotations ["
+              + method.parameterAnnotationsList.toSmaliString()
+              + "] on "
+              + method.method.toSourceString());
     }
   }
 
   private static void checkFieldAnnotations(DexEncodedField field) throws LambdaStructureError {
-    if (!field.annotations.isEmpty()) {
-      throw new LambdaStructureError("unexpected field annotations [" +
-          field.annotations.toSmaliString() + "] on " + field.field.toSourceString());
+    if (field.hasAnnotation()) {
+      throw new LambdaStructureError(
+          "unexpected field annotations ["
+              + field.annotations().toSmaliString()
+              + "] on "
+              + field.field.toSourceString());
     }
   }
 
@@ -231,8 +237,8 @@
   }
 
   @SafeVarargs
-  static <T extends AccessFlags> void checkAccessFlags(String message, int actual, T... expected)
-      throws LambdaStructureError {
+  private static <T extends AccessFlags> void checkAccessFlags(
+      String message, int actual, T... expected) throws LambdaStructureError {
     for (T flag : expected) {
       if (actual == flag.materialize()) {
         return;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java
index e2999df..d61b6ae 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java
@@ -25,6 +25,9 @@
 
   private final AppView<?> appView;
 
+  /** The library types that are modeled. */
+  private final Set<DexType> modeledLibraryTypes = Sets.newIdentityHashSet();
+
   private final Map<DexType, LibraryMethodModelCollection> libraryMethodModelCollections =
       new IdentityHashMap<>();
 
@@ -37,12 +40,35 @@
     if (LogMethodOptimizer.isEnabled(appView)) {
       register(new LogMethodOptimizer(appView));
     }
+
+    LibraryOptimizationInfoInitializer libraryOptimizationInfoInitializer =
+        new LibraryOptimizationInfoInitializer(appView);
+    libraryOptimizationInfoInitializer.run();
+    modeledLibraryTypes.addAll(libraryOptimizationInfoInitializer.getModeledLibraryTypes());
+  }
+
+  /**
+   * Returns true if {@param type} is a library type that is modeled in the compiler.
+   *
+   * <p>In order for library modeling to work in D8, we return a definition for invoke instructions
+   * that are guaranteed to dispatch to a library method in {@link
+   * InvokeMethod#lookupSingleTarget(AppView, DexType)}. As part of that, we bail-out if the holder
+   * of the targeted method is not a library class. However, what is usually on the library path
+   * will be on the program path when compiling the framework itself. To ensure that our library
+   * modeling works also for the framework compilation, we maintain the set of types that we model,
+   * and treat these types as library types in {@link InvokeMethod#lookupSingleTarget(AppView,
+   * DexType)} although they are on the program path.
+   */
+  public boolean isModeled(DexType type) {
+    return modeledLibraryTypes.contains(type);
   }
 
   private void register(LibraryMethodModelCollection optimizer) {
+    DexType modeledType = optimizer.getType();
     LibraryMethodModelCollection existing =
-        libraryMethodModelCollections.put(optimizer.getType(), optimizer);
+        libraryMethodModelCollections.put(modeledType, optimizer);
     assert existing == null;
+    modeledLibraryTypes.add(modeledType);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
index 050640c..4cd152f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
@@ -8,8 +8,11 @@
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
+import com.google.common.collect.Sets;
 import java.util.BitSet;
+import java.util.Set;
 
 public class LibraryOptimizationInfoInitializer {
 
@@ -17,21 +20,26 @@
   private final DexItemFactory dexItemFactory;
 
   private final OptimizationFeedbackSimple feedback = OptimizationFeedbackSimple.getInstance();
+  private final Set<DexType> modeledLibraryTypes = Sets.newIdentityHashSet();
 
-  public LibraryOptimizationInfoInitializer(AppView<?> appView) {
+  LibraryOptimizationInfoInitializer(AppView<?> appView) {
     this.appView = appView;
     this.dexItemFactory = appView.dexItemFactory();
   }
 
-  public void run() {
+  void run() {
     modelLibraryMethodsReturningNonNull();
     modelLibraryMethodsReturningReceiver();
     modelRequireNonNullMethods();
   }
 
+  Set<DexType> getModeledLibraryTypes() {
+    return modeledLibraryTypes;
+  }
+
   private void modelLibraryMethodsReturningNonNull() {
     for (DexMethod method : dexItemFactory.libraryMethodsReturningNonNull) {
-      DexEncodedMethod definition = appView.definitionFor(method);
+      DexEncodedMethod definition = lookupMethod(method);
       if (definition != null) {
         feedback.methodNeverReturnsNull(definition);
       }
@@ -40,7 +48,7 @@
 
   private void modelLibraryMethodsReturningReceiver() {
     for (DexMethod method : dexItemFactory.libraryMethodsReturningReceiver) {
-      DexEncodedMethod definition = appView.definitionFor(method);
+      DexEncodedMethod definition = lookupMethod(method);
       if (definition != null) {
         feedback.methodReturnsArgument(definition, 0);
       }
@@ -49,7 +57,7 @@
 
   private void modelRequireNonNullMethods() {
     for (DexMethod requireNonNullMethod : dexItemFactory.objectsMethods.requireNonNullMethods()) {
-      DexEncodedMethod definition = appView.definitionFor(requireNonNullMethod);
+      DexEncodedMethod definition = lookupMethod(requireNonNullMethod);
       if (definition != null) {
         feedback.methodReturnsArgument(definition, 0);
 
@@ -63,4 +71,13 @@
       }
     }
   }
+
+  private DexEncodedMethod lookupMethod(DexMethod method) {
+    DexEncodedMethod encodedMethod = appView.definitionFor(method);
+    if (encodedMethod != null) {
+      modeledLibraryTypes.add(method.holder);
+      return encodedMethod;
+    }
+    return null;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java
index 6cd36b3..35220c7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java
@@ -42,7 +42,7 @@
     this.appView = appView;
 
     DexItemFactory dexItemFactory = appView.dexItemFactory();
-    DexType logType = dexItemFactory.createType("Landroid/util/Log;");
+    DexType logType = dexItemFactory.androidUtilLogType;
     this.logType = logType;
     this.isLoggableMethod =
         dexItemFactory.createMethod(
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 1600057..d458662 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -139,7 +139,7 @@
     int access = clazz.accessFlags.getAsCfAccessFlags();
     String desc = namingLens.lookupDescriptor(clazz.type).toString();
     String name = namingLens.lookupInternalName(clazz.type);
-    String signature = getSignature(clazz.annotations);
+    String signature = getSignature(clazz.annotations());
     String superName =
         clazz.type == options.itemFactory.objectType
             ? null
@@ -149,8 +149,8 @@
       interfaces[i] = namingLens.lookupInternalName(clazz.interfaces.values[i]);
     }
     writer.visit(version, access, name, signature, superName, interfaces);
-    writeAnnotations(writer::visitAnnotation, clazz.annotations.annotations);
-    ImmutableMap<DexString, DexValue> defaults = getAnnotationDefaults(clazz.annotations);
+    writeAnnotations(writer::visitAnnotation, clazz.annotations().annotations);
+    ImmutableMap<DexString, DexValue> defaults = getAnnotationDefaults(clazz.annotations());
 
     if (clazz.getEnclosingMethod() != null) {
       clazz.getEnclosingMethod().write(writer, namingLens);
@@ -291,10 +291,10 @@
     int access = field.accessFlags.getAsCfAccessFlags();
     String name = namingLens.lookupName(field.field).toString();
     String desc = namingLens.lookupDescriptor(field.field.type).toString();
-    String signature = getSignature(field.annotations);
+    String signature = getSignature(field.annotations());
     Object value = getStaticValue(field);
     FieldVisitor visitor = writer.visitField(access, name, desc, signature, value);
-    writeAnnotations(visitor::visitAnnotation, field.annotations.annotations);
+    writeAnnotations(visitor::visitAnnotation, field.annotations().annotations);
     visitor.visitEnd();
   }
 
@@ -306,8 +306,8 @@
     int access = method.accessFlags.getAsCfAccessFlags();
     String name = namingLens.lookupName(method.method).toString();
     String desc = method.descriptor(namingLens);
-    String signature = getSignature(method.annotations);
-    String[] exceptions = getExceptions(method.annotations);
+    String signature = getSignature(method.annotations());
+    String[] exceptions = getExceptions(method.annotations());
     MethodVisitor visitor = writer.visitMethod(access, name, desc, signature, exceptions);
     if (defaults.containsKey(method.method.name)) {
       AnnotationVisitor defaultVisitor = visitor.visitAnnotationDefault();
@@ -316,8 +316,8 @@
         defaultVisitor.visitEnd();
       }
     }
-    writeMethodParametersAnnotation(visitor, method.annotations.annotations);
-    writeAnnotations(visitor::visitAnnotation, method.annotations.annotations);
+    writeMethodParametersAnnotation(visitor, method.annotations().annotations);
+    writeAnnotations(visitor::visitAnnotation, method.annotations().annotations);
     writeParameterAnnotations(visitor, method.parameterAnnotationsList);
     if (!method.shouldNotHaveCode()) {
       writeCode(method, visitor, classFileVersion);
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 a195f97..fec6a34 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -25,10 +25,7 @@
       Kotlin kotlin,
       DexClass clazz,
       DiagnosticsHandler reporter) {
-    if (clazz.annotations.isEmpty()) {
-      return null;
-    }
-    DexAnnotation meta = clazz.annotations.getFirstMatching(kotlin.metadata.kotlinMetadataType);
+    DexAnnotation meta = clazz.annotations().getFirstMatching(kotlin.metadata.kotlinMetadataType);
     if (meta != null) {
       try {
         return createKotlinInfo(kotlin, clazz, meta.annotation);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
index 7a1a343..56d9359 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.kotlin;
 
 import static com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.toRenamedKmFunction;
-import static com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.toRenamedKmFunctionAsExtension;
 
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
@@ -119,21 +118,14 @@
         continue;
       }
 
-      if (method.isKotlinExtensionFunction()) {
-        KmFunction extension = toRenamedKmFunctionAsExtension(method, appView, lens);
-        if (extension != null) {
-          functions.add(extension);
-        }
-        continue;
-      }
-      if (method.isKotlinFunction()) {
+      if (method.isKotlinFunction() || method.isKotlinExtensionFunction()) {
         KmFunction function = toRenamedKmFunction(method, appView, lens);
         if (function != null) {
           functions.add(function);
         }
         continue;
       }
-      if (method.isKotlinProperty()) {
+      if (method.isKotlinProperty() || method.isKotlinExtensionProperty()) {
         String name = method.getKotlinMemberInfo().propertyName;
         assert name != null;
         KmPropertyGroup.Builder builder =
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java
index 62b5355..50058ec 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java
@@ -14,34 +14,84 @@
 import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmFunctionProcessor;
 import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmPropertyProcessor;
 import com.android.tools.r8.utils.Reporter;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import kotlinx.metadata.KmDeclarationContainer;
 import kotlinx.metadata.KmFunction;
 import kotlinx.metadata.KmProperty;
+import kotlinx.metadata.KmValueParameter;
 
 // Provides access to field/method-level Kotlin information.
 public class KotlinMemberInfo {
-  private static KotlinMemberInfo NO_KOTLIN_MEMBER_INFO = new KotlinMemberInfo(MemberKind.NONE, 0);
+  private static final List<KmValueParameter> EMPTY_PARAM = ImmutableList.of();
+  private static final List<KotlinValueParameterInfo> EMPTY_PARAM_INFO = ImmutableList.of();
+
+  private static final KotlinMemberInfo NO_KOTLIN_MEMBER_INFO =
+      new KotlinMemberInfo(MemberKind.NONE, 0, EMPTY_PARAM);
 
   public static KotlinMemberInfo getNoKotlinMemberInfo() {
     return NO_KOTLIN_MEMBER_INFO;
   }
 
   public final MemberKind memberKind;
-  // Original flag. May be necessary to keep Kotlin-specific flag, e.g., inline function.
+  // Original member flag. May be necessary to keep Kotlin-specific flag, e.g., suspend function.
   final int flag;
   // Original property name for (extension) property. Otherwise, null.
   final String propertyName;
+  // Information from original KmValueParameter(s) if available. Otherwise, null.
+  private final List<KotlinValueParameterInfo> valueParameterInfos;
 
-  private KotlinMemberInfo(MemberKind memberKind, int flag) {
-    this(memberKind, flag, null);
+  // Constructor for KmFunction
+  private KotlinMemberInfo(
+      MemberKind memberKind, int flag, List<KmValueParameter> kmValueParameters) {
+    this(memberKind, flag, null, kmValueParameters);
   }
 
+  // Constructor for a backing field and a getter in KmProperty
   private KotlinMemberInfo(MemberKind memberKind, int flag, String propertyName) {
+    this(memberKind, flag, propertyName, EMPTY_PARAM);
+  }
+
+  // Constructor for a setter in KmProperty
+  private KotlinMemberInfo(
+      MemberKind memberKind,
+      int flag,
+      String propertyName,
+      KmValueParameter kmValueParameter) {
+    this(memberKind, flag, propertyName,
+        kmValueParameter != null ? ImmutableList.of(kmValueParameter) : EMPTY_PARAM);
+  }
+
+  private KotlinMemberInfo(
+      MemberKind memberKind,
+      int flag,
+      String propertyName,
+      List<KmValueParameter> kmValueParameters) {
     this.memberKind = memberKind;
     this.flag = flag;
     this.propertyName = propertyName;
+    assert kmValueParameters != null;
+    if (kmValueParameters.isEmpty()) {
+      this.valueParameterInfos = EMPTY_PARAM_INFO;
+    } else {
+      this.valueParameterInfos = new ArrayList<>(kmValueParameters.size());
+      for (KmValueParameter kmValueParameter : kmValueParameters) {
+        valueParameterInfos.add(KotlinValueParameterInfo.fromKmValueParameter(kmValueParameter));
+      }
+    }
+  }
+
+  KotlinValueParameterInfo getValueParameterInfo(int i) {
+    if (valueParameterInfos.isEmpty()) {
+      return null;
+    }
+    if (i < 0 || i >= valueParameterInfos.size()) {
+      return null;
+    }
+    return valueParameterInfos.get(i);
   }
 
   public enum MemberKind {
@@ -151,10 +201,16 @@
         KmFunction kmFunction = kmFunctionMap.get(key);
         if (isExtension(kmFunction)) {
           method.setKotlinMemberInfo(
-              new KotlinMemberInfo(MemberKind.EXTENSION_FUNCTION, kmFunction.getFlags()));
+              new KotlinMemberInfo(
+                  MemberKind.EXTENSION_FUNCTION,
+                  kmFunction.getFlags(),
+                  kmFunction.getValueParameters()));
         } else {
           method.setKotlinMemberInfo(
-              new KotlinMemberInfo(MemberKind.FUNCTION, kmFunction.getFlags()));
+              new KotlinMemberInfo(
+                  MemberKind.FUNCTION,
+                  kmFunction.getFlags(),
+                  kmFunction.getValueParameters()));
         }
       } else if (kmPropertyGetterMap.containsKey(key)) {
         KmProperty kmProperty = kmPropertyGetterMap.get(key);
@@ -176,11 +232,15 @@
               new KotlinMemberInfo(
                   MemberKind.EXTENSION_PROPERTY_SETTER,
                   kmProperty.getFlags(),
-                  kmProperty.getName()));
+                  kmProperty.getName(),
+                  kmProperty.getSetterParameter()));
         } else {
           method.setKotlinMemberInfo(
               new KotlinMemberInfo(
-                  MemberKind.PROPERTY_SETTER, kmProperty.getFlags(), kmProperty.getName()));
+                  MemberKind.PROPERTY_SETTER,
+                  kmProperty.getFlags(),
+                  kmProperty.getName(),
+                  kmProperty.getSetterParameter()));
         }
       }
     }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index b295da3..9507b32 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -47,7 +47,7 @@
 
   public static void removeKotlinMetadataFromRenamedClass(AppView<?> appView, DexClass clazz) {
     // Remove @Metadata in DexAnnotation form if a class is renamed.
-    clazz.annotations = clazz.annotations.keepIf(anno -> isNotKotlinMetadata(appView, anno));
+    clazz.setAnnotations(clazz.annotations().keepIf(anno -> isNotKotlinMetadata(appView, anno)));
     // Clear associated {@link KotlinInfo} to avoid accidentally deserialize it back to
     // DexAnnotation we've just removed above.
     if (clazz.isProgramClass()) {
@@ -72,11 +72,12 @@
             // TODO(b/70169921): if this option is settled down, this assertion is meaningless.
             assert lens.lookupType(clazz.type, appView.dexItemFactory()) == clazz.type
                     || appView.options().enableKotlinMetadataRewritingForRenamedClasses
-                : clazz.toSourceString() + " != "
+                : clazz.toSourceString()
+                    + " != "
                     + lens.lookupType(clazz.type, appView.dexItemFactory());
 
             DexAnnotation oldMeta =
-                clazz.annotations.getFirstMatching(kotlin.metadata.kotlinMetadataType);
+                clazz.annotations().getFirstMatching(kotlin.metadata.kotlinMetadataType);
             // If @Metadata is already gone, e.g., by {@link AnnotationRemover} if type Metadata is
             // determined as dead (e.g., due to no keep rule), nothing to do.
             if (oldMeta == null) {
@@ -86,11 +87,11 @@
             kotlinInfo.rewrite(appView, lens);
 
             DexAnnotation newMeta = createKotlinMetadataAnnotation(kotlinInfo.createHeader());
-            clazz.annotations = clazz.annotations.rewrite(anno -> anno == oldMeta ? newMeta : anno);
+            clazz.setAnnotations(
+                clazz.annotations().rewrite(anno -> anno == oldMeta ? newMeta : anno));
           }
         },
-        executorService
-    );
+        executorService);
   }
 
   private DexAnnotation createKotlinMetadataAnnotation(KotlinClassHeader header) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
index 94c65e3..6e959b6 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
@@ -97,7 +97,7 @@
     KmConstructor kmConstructor = new KmConstructor(method.accessFlags.getAsKotlinFlags());
     JvmExtensionsKt.setSignature(kmConstructor, toJvmMethodSignature(method.method));
     List<KmValueParameter> parameters = kmConstructor.getValueParameters();
-    if (!populateKmValueParameters(parameters, method, appView, lens, false)) {
+    if (!populateKmValueParameters(parameters, method, appView, lens)) {
       return null;
     }
     return kmConstructor;
@@ -107,21 +107,6 @@
       DexEncodedMethod method,
       AppView<AppInfoWithLiveness> appView,
       NamingLens lens) {
-    return toRenamedKmFunctionHelper(method, appView, lens, false);
-  }
-
-  static KmFunction toRenamedKmFunctionAsExtension(
-      DexEncodedMethod method,
-      AppView<AppInfoWithLiveness> appView,
-      NamingLens lens) {
-    return toRenamedKmFunctionHelper(method, appView, lens, true);
-  }
-
-  private static KmFunction toRenamedKmFunctionHelper(
-      DexEncodedMethod method,
-      AppView<AppInfoWithLiveness> appView,
-      NamingLens lens,
-      boolean isExtension) {
     // For library overrides, synthesize @Metadata always.
     // For regular methods, make sure it is live or pinned.
     if (!method.isLibraryMethodOverride().isTrue()
@@ -146,7 +131,7 @@
       return null;
     }
     kmFunction.setReturnType(kmReturnType);
-    if (isExtension) {
+    if (method.isKotlinExtensionFunction()) {
       assert method.method.proto.parameters.values.length > 0
           : method.method.toSourceString();
       KmType kmReceiverType =
@@ -157,7 +142,7 @@
       kmFunction.setReceiverParameterType(kmReceiverType);
     }
     List<KmValueParameter> parameters = kmFunction.getValueParameters();
-    if (!populateKmValueParameters(parameters, method, appView, lens, isExtension)) {
+    if (!populateKmValueParameters(parameters, method, appView, lens)) {
       return null;
     }
     return kmFunction;
@@ -167,24 +152,53 @@
       List<KmValueParameter> parameters,
       DexEncodedMethod method,
       AppView<AppInfoWithLiveness> appView,
-      NamingLens lens,
-      boolean isExtension) {
+      NamingLens lens) {
+    boolean isExtension = method.isKotlinExtensionFunction();
     for (int i = isExtension ? 1 : 0; i < method.method.proto.parameters.values.length; i++) {
-      DexType paramType = method.method.proto.parameters.values[i];
+      DexType parameterType = method.method.proto.parameters.values[i];
       DebugLocalInfo debugLocalInfo = method.getParameterInfo().get(i);
       String parameterName = debugLocalInfo != null ? debugLocalInfo.name.toString() : ("p" + i);
-      // TODO(b/70169921): Consult kotlinx.metadata.Flag.ValueParameter.
-      KmValueParameter kmValueParameter = new KmValueParameter(flagsOf(), parameterName);
-      KmType kmParamType = toRenamedKmType(paramType, appView, lens);
-      if (kmParamType == null) {
+      KotlinValueParameterInfo valueParameterInfo =
+          method.getKotlinMemberInfo().getValueParameterInfo(isExtension ? i - 1 : i);
+      KmValueParameter kmValueParameter =
+          toRewrittenKmValueParameter(
+              valueParameterInfo, parameterType, parameterName, appView, lens);
+      if (kmValueParameter == null) {
         return false;
       }
-      kmValueParameter.setType(kmParamType);
       parameters.add(kmValueParameter);
     }
     return true;
   }
 
+  private static KmValueParameter toRewrittenKmValueParameter(
+      KotlinValueParameterInfo valueParameterInfo,
+      DexType parameterType,
+      String candidateParameterName,
+      AppView<AppInfoWithLiveness> appView,
+      NamingLens lens) {
+    KmType kmParamType = toRenamedKmType(parameterType, appView, lens);
+    if (kmParamType == null) {
+      return null;
+    }
+    int flag = valueParameterInfo != null ? valueParameterInfo.flag : flagsOf();
+    String name = valueParameterInfo != null ? valueParameterInfo.name : candidateParameterName;
+    KmValueParameter kmValueParameter = new KmValueParameter(flag, name);
+    kmValueParameter.setType(kmParamType);
+    if (valueParameterInfo != null && valueParameterInfo.isVararg) {
+      if (!parameterType.isArrayType()) {
+        return null;
+      }
+      DexType elementType = parameterType.toBaseType(appView.dexItemFactory());
+      KmType kmElementType = toRenamedKmType(elementType, appView, lens);
+      if (kmElementType == null) {
+        return null;
+      }
+      kmValueParameter.setVarargElementType(kmElementType);
+    }
+    return kmValueParameter;
+  }
+
   /**
    * A group of a field, and methods that correspond to a Kotlin property.
    *
@@ -315,18 +329,26 @@
       KmType kmPropertyType = null;
       KmType kmReceiverType = null;
 
+      // A flag to indicate we can rename the property name. This will become false if any member
+      // is pinned. Then, we conservatively assume that users want the property to be pinned too.
+      // That is, we won't rename the property even though some other members could be renamed.
+      boolean canChangePropertyName = true;
+      // A candidate property name. Not overwritten by the following members, hence the order of
+      // preference: a backing field, getter, and setter.
+      String renamedPropertyName = name;
       if (field != null) {
-        DexField renamedField = lens.lookupField(field.field, appView.dexItemFactory());
-        if (renamedField == null) {
-          // Bail out if we can't find a renamed backing field.
-          return null;
+        if (appView.appInfo().isPinned(field.field)) {
+          canChangePropertyName = false;
         }
-        kmProperty.setName(renamedField.name.toString());
+        DexField renamedField = lens.lookupField(field.field, appView.dexItemFactory());
+        if (canChangePropertyName && renamedField.name != field.field.name) {
+          renamedPropertyName = renamedField.name.toString();
+        }
         kmPropertyType = toRenamedKmType(field.field.type, appView, lens);
         if (kmPropertyType != null) {
           kmProperty.setReturnType(kmPropertyType);
         }
-        JvmExtensionsKt.setFieldSignature(kmProperty, toJvmFieldSignature(field.field));
+        JvmExtensionsKt.setFieldSignature(kmProperty, toJvmFieldSignature(renamedField));
       }
 
       GetterSetterCriteria criteria = checkGetterCriteria();
@@ -360,8 +382,17 @@
             return null;
           }
         }
+        if (appView.appInfo().isPinned(getter.method)) {
+          canChangePropertyName = false;
+        }
+        DexMethod renamedGetter = lens.lookupMethod(getter.method, appView.dexItemFactory());
+        if (canChangePropertyName
+            && renamedGetter.name != getter.method.name
+            && renamedPropertyName.equals(name)) {
+          renamedPropertyName = renamedGetter.name.toString();
+        }
         kmProperty.setGetterFlags(getter.accessFlags.getAsKotlinFlags());
-        JvmExtensionsKt.setGetterSignature(kmProperty, toJvmMethodSignature(getter.method));
+        JvmExtensionsKt.setGetterSignature(kmProperty, toJvmMethodSignature(renamedGetter));
       }
 
       criteria = checkSetterCriteria();
@@ -393,25 +424,40 @@
           }
         }
         int valueIndex = isExtension ? 1 : 0;
+        DexType valueType = setter.method.proto.parameters.values[valueIndex];
         if (kmPropertyType == null) {
           // The property type is not set yet.
-          kmPropertyType =
-              toRenamedKmType(setter.method.proto.parameters.values[valueIndex], appView, lens);
+          kmPropertyType = toRenamedKmType(valueType, appView, lens);
           if (kmPropertyType != null) {
             kmProperty.setReturnType(kmPropertyType);
           }
         } else {
           // If property type is set already (via either backing field or getter),
           // make sure it's consistent.
-          KmType kmPropertyTypeFromSetter =
-              toRenamedKmType(setter.method.proto.parameters.values[valueIndex], appView, lens);
+          KmType kmPropertyTypeFromSetter = toRenamedKmType(valueType, appView, lens);
           if (!getDescriptorFromKmType(kmPropertyType)
               .equals(getDescriptorFromKmType(kmPropertyTypeFromSetter))) {
             return null;
           }
         }
+        KotlinValueParameterInfo valueParameterInfo =
+            setter.getKotlinMemberInfo().getValueParameterInfo(valueIndex);
+        KmValueParameter kmValueParameter =
+            toRewrittenKmValueParameter(valueParameterInfo, valueType, "value", appView, lens);
+        if (kmValueParameter != null) {
+          kmProperty.setSetterParameter(kmValueParameter);
+        }
+        if (appView.appInfo().isPinned(setter.method)) {
+          canChangePropertyName = false;
+        }
+        DexMethod renamedSetter = lens.lookupMethod(setter.method, appView.dexItemFactory());
+        if (canChangePropertyName
+            && renamedSetter.name != setter.method.name
+            && renamedPropertyName.equals(name)) {
+          renamedPropertyName = renamedSetter.name.toString();
+        }
         kmProperty.setSetterFlags(setter.accessFlags.getAsKotlinFlags());
-        JvmExtensionsKt.setSetterSignature(kmProperty, toJvmMethodSignature(setter.method));
+        JvmExtensionsKt.setSetterSignature(kmProperty, toJvmMethodSignature(renamedSetter));
       }
 
       // If the property type remains null at the end, bail out to synthesize this property.
@@ -422,6 +468,11 @@
       if (isExtension && kmReceiverType == null) {
         return null;
       }
+      // Rename the property name if and only if none of participating members is pinned, and
+      // any of them is indeed renamed (to a new name).
+      if (canChangePropertyName && !renamedPropertyName.equals(name)) {
+        kmProperty.setName(renamedPropertyName);
+      }
       return kmProperty;
     }
 
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
new file mode 100644
index 0000000..95d91f8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2020, 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.kotlin;
+
+import kotlinx.metadata.KmValueParameter;
+
+// Provides access to Kotlin information about value parameter.
+class KotlinValueParameterInfo {
+  // TODO(b/70169921): When to use original param name v.s. when to *not* use?
+  // Original parameter name.
+  final String name;
+  // Original parameter flag, e.g., has default value.
+  final int flag;
+  // Indicates whether the formal parameter is originally `vararg`.
+  final boolean isVararg;
+
+  private KotlinValueParameterInfo(String name, int flag, boolean isVararg) {
+    this.name = name;
+    this.flag = flag;
+    this.isVararg = isVararg;
+  }
+
+  static KotlinValueParameterInfo fromKmValueParameter(KmValueParameter kmValueParameter) {
+    return new KotlinValueParameterInfo(
+        kmValueParameter.getName(),
+        kmValueParameter.getFlags(),
+        kmValueParameter.getVarargElementType() != null);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
index 45c59a8..e891f95 100644
--- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -54,28 +54,28 @@
     // ClassNameMinifier.
     for (DexProgramClass clazz : classes) {
       genericSignatureCollector.setCurrentClassContext(clazz);
-      clazz.annotations =
+      clazz.setAnnotations(
           rewriteGenericSignatures(
-              clazz.annotations,
+              clazz.annotations(),
               genericSignatureParser::parseClassSignature,
               genericSignatureCollector::getRenamedSignature,
-              (signature, e) -> parseError(clazz, clazz.getOrigin(), signature, e));
+              (signature, e) -> parseError(clazz, clazz.getOrigin(), signature, e)));
       clazz.forEachField(
           field ->
-              field.annotations =
+              field.setAnnotations(
                   rewriteGenericSignatures(
-                      field.annotations,
+                      field.annotations(),
                       genericSignatureParser::parseFieldSignature,
                       genericSignatureCollector::getRenamedSignature,
-                      (signature, e) -> parseError(field, clazz.getOrigin(), signature, e)));
+                      (signature, e) -> parseError(field, clazz.getOrigin(), signature, e))));
       clazz.forEachMethod(
           method ->
-              method.annotations =
+              method.setAnnotations(
                   rewriteGenericSignatures(
-                      method.annotations,
+                      method.annotations(),
                       genericSignatureParser::parseMethodSignature,
                       genericSignatureCollector::getRenamedSignature,
-                      (signature, e) -> parseError(method, clazz.getOrigin(), signature, e)));
+                      (signature, e) -> parseError(method, clazz.getOrigin(), signature, e))));
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index 057875d..0edcea8 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.utils.OptionsParsing.ParseContext;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.Timing;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -118,10 +119,14 @@
    */
   public static void run(RetraceCommand command) {
     try {
+      Timing timing = Timing.create("R8 retrace", command.printMemory());
+      timing.begin("Read proguard map");
       ClassNameMapper classNameMapper =
           ClassNameMapper.mapperFromString(command.proguardMapProducer.get());
+      timing.end();
       RetraceBase retraceBase = RetraceBaseImpl.create(classNameMapper);
       RetraceCommandLineResult result;
+      timing.begin("Parse and Retrace");
       if (command.regularExpression != null) {
         result =
             new RetraceRegularExpression(
@@ -136,7 +141,13 @@
                     retraceBase, command.stackTrace, command.diagnosticsHandler, command.isVerbose)
                 .retrace();
       }
+      timing.end();
+      timing.begin("Report result");
       command.retracedStackTraceConsumer.accept(result.getNodes());
+      timing.end();
+      if (command.printTimes()) {
+        timing.report();
+      }
     } catch (IOException ex) {
       command.diagnosticsHandler.error(
           new StringDiagnostic("Could not open mapping input stream: " + ex.getMessage()));
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java b/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
index 93addc4..64cf59a 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
@@ -40,6 +40,14 @@
     assert this.retracedStackTraceConsumer != null;
   }
 
+  public boolean printTimes() {
+    return System.getProperty("com.android.tools.r8.printtimes") != null;
+  }
+
+  public boolean printMemory() {
+    return System.getProperty("com.android.tools.r8.printmemory") != null;
+  }
+
   /**
    * Utility method for obtaining a RetraceCommand builder.
    *
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java b/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java
index 356f609..0fe561c 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java
@@ -27,21 +27,21 @@
 
   public void run(Iterable<DexProgramClass> classes) {
     for (DexProgramClass clazz : classes) {
-      clazz.annotations = clazz.annotations.rewrite(this::rewriteAnnotation);
+      clazz.setAnnotations(clazz.annotations().rewrite(this::rewriteAnnotation));
       clazz.forEachMethod(this::processMethod);
       clazz.forEachField(this::processField);
     }
   }
 
   private void processMethod(DexEncodedMethod method) {
-    method.annotations = method.annotations.rewrite(this::rewriteAnnotation);
+    method.setAnnotations(method.annotations().rewrite(this::rewriteAnnotation));
     method.parameterAnnotationsList =
         method.parameterAnnotationsList.rewrite(
             dexAnnotationSet -> dexAnnotationSet.rewrite(this::rewriteAnnotation));
   }
 
   private void processField(DexEncodedField field) {
-    field.annotations = field.annotations.rewrite(this::rewriteAnnotation);
+    field.setAnnotations(field.annotations().rewrite(this::rewriteAnnotation));
   }
 
   private DexAnnotation rewriteAnnotation(DexAnnotation original) {
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index fd3e7f5..6cfa6d8 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationElement;
-import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexDefinition;
 import com.android.tools.r8.graph.DexEncodedAnnotation;
@@ -157,7 +156,7 @@
   }
 
   private static boolean hasSignatureAnnotation(DexProgramClass clazz, DexItemFactory itemFactory) {
-    for (DexAnnotation annotation : clazz.annotations.annotations) {
+    for (DexAnnotation annotation : clazz.annotations().annotations) {
       if (DexAnnotation.isSignatureAnnotation(annotation, itemFactory)) {
         return true;
       }
@@ -230,23 +229,23 @@
   public void run() {
     for (DexProgramClass clazz : appView.appInfo().classes()) {
       stripAttributes(clazz);
-      clazz.annotations =
-          clazz.annotations.rewrite(annotation -> rewriteAnnotation(clazz, annotation));
+      clazz.setAnnotations(
+          clazz.annotations().rewrite(annotation -> rewriteAnnotation(clazz, annotation)));
       clazz.forEachMethod(this::processMethod);
       clazz.forEachField(this::processField);
     }
   }
 
   private void processMethod(DexEncodedMethod method) {
-    method.annotations =
-        method.annotations.rewrite(annotation -> rewriteAnnotation(method, annotation));
+    method.setAnnotations(
+        method.annotations().rewrite(annotation -> rewriteAnnotation(method, annotation)));
     method.parameterAnnotationsList =
         method.parameterAnnotationsList.keepIf(this::filterParameterAnnotations);
   }
 
   private void processField(DexEncodedField field) {
-    field.annotations =
-        field.annotations.rewrite(annotation -> rewriteAnnotation(field, annotation));
+    field.setAnnotations(
+        field.annotations().rewrite(annotation -> rewriteAnnotation(field, annotation)));
   }
 
   private DexAnnotation rewriteAnnotation(DexDefinition holder, DexAnnotation original) {
@@ -359,13 +358,8 @@
 
   public static void clearAnnotations(AppView<?> appView) {
     for (DexProgramClass clazz : appView.appInfo().classes()) {
-      clazz.annotations = DexAnnotationSet.empty();
-      for (DexEncodedMethod method : clazz.methods()) {
-        method.annotations = DexAnnotationSet.empty();
-      }
-      for (DexEncodedField field : clazz.fields()) {
-        field.annotations = DexAnnotationSet.empty();
-      }
+      clazz.clearAnnotations();
+      clazz.members().forEach(DexDefinition::clearAnnotations);
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index dcc6877..69ed3b0 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -26,6 +26,8 @@
 import com.android.tools.r8.graph.FieldAccessInfoImpl;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollection;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
 import com.android.tools.r8.graph.PresortedComparable;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
@@ -62,20 +64,18 @@
 /** Encapsulates liveness and reachability information for an application. */
 public class AppInfoWithLiveness extends AppInfoWithSubtyping {
 
+  /** Set of types that are mentioned in the program, but for which no definition exists. */
+  private final Set<DexType> missingTypes;
   /**
    * Set of types that are mentioned in the program. We at least need an empty abstract classitem
    * for these.
    */
   private final Set<DexType> liveTypes;
-  /** Set of annotation types that are instantiated. */
-  private final Set<DexType> instantiatedAnnotationTypes;
   /**
    * Set of service types (from META-INF/services/) that may have been instantiated reflectively via
    * ServiceLoader.load() or ServiceLoader.loadInstalled().
    */
   public final Set<DexType> instantiatedAppServices;
-  /** Set of types that are actually instantiated. These cannot be abstract. */
-  final Set<DexType> instantiatedTypes;
   /** Cache for {@link #isInstantiatedDirectlyOrIndirectly(DexProgramClass)}. */
   private final IdentityHashMap<DexType, Boolean> indirectlyInstantiatedTypes =
       new IdentityHashMap<>();
@@ -109,6 +109,8 @@
    * each field. The latter is used, for example, during member rebinding.
    */
   private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection;
+  /** Information about instantiated classes and their allocation sites. */
+  private final ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection;
   /** Set of all methods referenced in virtual invokes, along with calling context. */
   public final SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes;
   /** Set of all methods referenced in interface invokes, along with calling context. */
@@ -190,10 +192,9 @@
   // TODO(zerny): Clean up the constructors so we have just one.
   AppInfoWithLiveness(
       DirectMappedDexApplication application,
+      Set<DexType> missingTypes,
       Set<DexType> liveTypes,
-      Set<DexType> instantiatedAnnotationTypes,
       Set<DexType> instantiatedAppServices,
-      Set<DexType> instantiatedTypes,
       SortedSet<DexMethod> targetedMethods,
       Set<DexMethod> failedResolutionTargets,
       SortedSet<DexMethod> bootstrapMethods,
@@ -201,6 +202,7 @@
       SortedSet<DexMethod> virtualMethodsTargetedByInvokeDirect,
       SortedSet<DexMethod> liveMethods,
       FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
+      ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
       SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes,
       SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes,
       SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes,
@@ -230,10 +232,9 @@
       Set<DexType> instantiatedLambdas,
       Set<DexType> constClassReferences) {
     super(application);
+    this.missingTypes = missingTypes;
     this.liveTypes = liveTypes;
-    this.instantiatedAnnotationTypes = instantiatedAnnotationTypes;
     this.instantiatedAppServices = instantiatedAppServices;
-    this.instantiatedTypes = instantiatedTypes;
     this.targetedMethods = targetedMethods;
     this.failedResolutionTargets = failedResolutionTargets;
     this.bootstrapMethods = bootstrapMethods;
@@ -241,6 +242,7 @@
     this.virtualMethodsTargetedByInvokeDirect = virtualMethodsTargetedByInvokeDirect;
     this.liveMethods = liveMethods;
     this.fieldAccessInfoCollection = fieldAccessInfoCollection;
+    this.objectAllocationInfoCollection = objectAllocationInfoCollection;
     this.pinnedItems = pinnedItems;
     this.mayHaveSideEffects = mayHaveSideEffects;
     this.noSideEffects = noSideEffects;
@@ -273,10 +275,9 @@
 
   public AppInfoWithLiveness(
       AppInfoWithSubtyping appInfoWithSubtyping,
+      Set<DexType> missingTypes,
       Set<DexType> liveTypes,
-      Set<DexType> instantiatedAnnotationTypes,
       Set<DexType> instantiatedAppServices,
-      Set<DexType> instantiatedTypes,
       SortedSet<DexMethod> targetedMethods,
       Set<DexMethod> failedResolutionTargets,
       SortedSet<DexMethod> bootstrapMethods,
@@ -284,6 +285,7 @@
       SortedSet<DexMethod> virtualMethodsTargetedByInvokeDirect,
       SortedSet<DexMethod> liveMethods,
       FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
+      ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
       SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes,
       SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes,
       SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes,
@@ -313,10 +315,9 @@
       Set<DexType> instantiatedLambdas,
       Set<DexType> constClassReferences) {
     super(appInfoWithSubtyping);
+    this.missingTypes = missingTypes;
     this.liveTypes = liveTypes;
-    this.instantiatedAnnotationTypes = instantiatedAnnotationTypes;
     this.instantiatedAppServices = instantiatedAppServices;
-    this.instantiatedTypes = instantiatedTypes;
     this.targetedMethods = targetedMethods;
     this.failedResolutionTargets = failedResolutionTargets;
     this.bootstrapMethods = bootstrapMethods;
@@ -324,6 +325,7 @@
     this.virtualMethodsTargetedByInvokeDirect = virtualMethodsTargetedByInvokeDirect;
     this.liveMethods = liveMethods;
     this.fieldAccessInfoCollection = fieldAccessInfoCollection;
+    this.objectAllocationInfoCollection = objectAllocationInfoCollection;
     this.pinnedItems = pinnedItems;
     this.mayHaveSideEffects = mayHaveSideEffects;
     this.noSideEffects = noSideEffects;
@@ -357,10 +359,9 @@
   private AppInfoWithLiveness(AppInfoWithLiveness previous) {
     this(
         previous,
+        previous.missingTypes,
         previous.liveTypes,
-        previous.instantiatedAnnotationTypes,
         previous.instantiatedAppServices,
-        previous.instantiatedTypes,
         previous.targetedMethods,
         previous.failedResolutionTargets,
         previous.bootstrapMethods,
@@ -368,6 +369,7 @@
         previous.virtualMethodsTargetedByInvokeDirect,
         previous.liveMethods,
         previous.fieldAccessInfoCollection,
+        previous.objectAllocationInfoCollection,
         previous.virtualInvokes,
         previous.interfaceInvokes,
         previous.superInvokes,
@@ -406,10 +408,9 @@
       Collection<DexReference> additionalPinnedItems) {
     this(
         application,
+        previous.missingTypes,
         previous.liveTypes,
-        previous.instantiatedAnnotationTypes,
         previous.instantiatedAppServices,
-        previous.instantiatedTypes,
         previous.targetedMethods,
         previous.failedResolutionTargets,
         previous.bootstrapMethods,
@@ -417,6 +418,7 @@
         previous.virtualMethodsTargetedByInvokeDirect,
         previous.liveMethods,
         previous.fieldAccessInfoCollection,
+        previous.objectAllocationInfoCollection,
         previous.virtualInvokes,
         previous.interfaceInvokes,
         previous.superInvokes,
@@ -458,10 +460,9 @@
       Map<DexField, Int2ReferenceMap<DexField>> switchMaps,
       Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps) {
     super(previous);
+    this.missingTypes = previous.missingTypes;
     this.liveTypes = previous.liveTypes;
-    this.instantiatedAnnotationTypes = previous.instantiatedAnnotationTypes;
     this.instantiatedAppServices = previous.instantiatedAppServices;
-    this.instantiatedTypes = previous.instantiatedTypes;
     this.instantiatedLambdas = previous.instantiatedLambdas;
     this.targetedMethods = previous.targetedMethods;
     this.failedResolutionTargets = previous.failedResolutionTargets;
@@ -470,6 +471,7 @@
     this.virtualMethodsTargetedByInvokeDirect = previous.virtualMethodsTargetedByInvokeDirect;
     this.liveMethods = previous.liveMethods;
     this.fieldAccessInfoCollection = previous.fieldAccessInfoCollection;
+    this.objectAllocationInfoCollection = previous.objectAllocationInfoCollection;
     this.pinnedItems = previous.pinnedItems;
     this.mayHaveSideEffects = previous.mayHaveSideEffects;
     this.noSideEffects = previous.noSideEffects;
@@ -500,6 +502,30 @@
     previous.markObsolete();
   }
 
+  private boolean dontAssertDefinitionFor = true;
+
+  @Override
+  public void enableDefinitionForAssert() {
+    dontAssertDefinitionFor = false;
+  }
+
+  @Override
+  public void disableDefinitionForAssert() {
+    dontAssertDefinitionFor = true;
+  }
+
+  @Override
+  public DexClass definitionFor(DexType type) {
+    DexClass definition = super.definitionFor(type);
+    assert dontAssertDefinitionFor
+        || definition != null
+        || missingTypes.contains(type)
+        // TODO(b/149363884): Remove this exception once fixed.
+        || type.toDescriptorString().endsWith("$Builder;")
+        : "Failed lookup of non-missing type: " + type;
+    return definition;
+  }
+
   public boolean isLiveProgramClass(DexProgramClass clazz) {
     return liveTypes.contains(clazz.type);
   }
@@ -689,6 +715,11 @@
     return fieldAccessInfoCollection;
   }
 
+  /** This method provides immutable access to `objectAllocationInfoCollection`. */
+  public ObjectAllocationInfoCollection getObjectAllocationInfoCollection() {
+    return objectAllocationInfoCollection;
+  }
+
   private boolean assertNoItemRemoved(Collection<DexReference> items, Collection<DexType> types) {
     Set<DexType> typeSet = ImmutableSet.copyOf(types);
     for (DexReference item : items) {
@@ -710,8 +741,8 @@
     assert checkIfObsolete();
     DexType type = clazz.type;
     return type.isD8R8SynthesizedClassType()
-        || instantiatedTypes.contains(type)
-        || instantiatedAnnotationTypes.contains(type);
+        || objectAllocationInfoCollection.isInstantiatedDirectly(clazz)
+        || (clazz.isAnnotation() && liveTypes.contains(type));
   }
 
   public boolean isInstantiatedIndirectly(DexProgramClass clazz) {
@@ -966,10 +997,9 @@
 
     return new AppInfoWithLiveness(
         application,
+        missingTypes,
         rewriteItems(liveTypes, lens::lookupType),
-        rewriteItems(instantiatedAnnotationTypes, lens::lookupType),
         rewriteItems(instantiatedAppServices, lens::lookupType),
-        rewriteItems(instantiatedTypes, lens::lookupType),
         lens.rewriteMethodsConservatively(targetedMethods),
         lens.rewriteMethodsConservatively(failedResolutionTargets),
         lens.rewriteMethodsConservatively(bootstrapMethods),
@@ -977,6 +1007,7 @@
         lens.rewriteMethodsConservatively(virtualMethodsTargetedByInvokeDirect),
         lens.rewriteMethodsConservatively(liveMethods),
         fieldAccessInfoCollection.rewrittenWithLens(application, lens),
+        objectAllocationInfoCollection.rewrittenWithLens(application, lens),
         rewriteKeysConservativelyWhileMergingValues(
             virtualInvokes, lens::lookupMethodInAllContexts),
         rewriteKeysConservativelyWhileMergingValues(
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index ba1bdb5..d0e971e 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
 import static com.android.tools.r8.graph.FieldAccessInfoImpl.MISSING_FIELD_ACCESS_INFO;
 import static com.android.tools.r8.naming.IdentifierNameStringUtils.identifyIdentifier;
 import static com.android.tools.r8.naming.IdentifierNameStringUtils.isReflectionMethod;
@@ -28,11 +29,13 @@
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.Descriptor;
 import com.android.tools.r8.graph.DexAnnotation;
+import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexDefinition;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItem;
@@ -46,9 +49,12 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.DirectMappedDexApplication.Builder;
 import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
 import com.android.tools.r8.graph.FieldAccessInfoImpl;
-import com.android.tools.r8.graph.KeyedDexItem;
+import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
 import com.android.tools.r8.graph.PresortedComparable;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.ResolutionResult;
@@ -172,6 +178,7 @@
   private final Map<DexMethod, Set<DexEncodedMethod>> staticInvokes = new IdentityHashMap<>();
   private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection =
       new FieldAccessInfoCollectionImpl();
+  private final ObjectAllocationInfoCollectionImpl.Builder objectAllocationInfoCollection;
   private final Set<DexCallSite> callSites = Sets.newIdentityHashSet();
 
   private final Set<DexReference> identifierNameStrings = Sets.newIdentityHashSet();
@@ -203,19 +210,20 @@
   /** Set of types whose class initializer may execute. */
   private final SetWithReportedReason<DexProgramClass> initializedTypes;
 
-  /** Set of live types defined in the library and classpath. Used to avoid duplicate tracing. */
+  /**
+   * Set of live types defined in the library and classpath.
+   *
+   * <p>Used to build a new app of just referenced types and avoid duplicate tracing.
+   */
   private final Set<DexClass> liveNonProgramTypes = Sets.newIdentityHashSet();
 
+  /** Set of missing types. */
+  private final Set<DexType> missingTypes = Sets.newIdentityHashSet();
+
   /** Mapping from each unused interface to the set of live types that implements the interface. */
   private final Map<DexProgramClass, Set<DexProgramClass>> unusedInterfaceTypes =
       new IdentityHashMap<>();
 
-  /** Set of annotation types that are instantiated. */
-  private final SetWithReason<DexAnnotation> liveAnnotations;
-
-  /** Set of types that are actually instantiated. These cannot be abstract. */
-  private final SetWithReason<DexProgramClass> instantiatedTypes;
-
   /** Set of all types that are instantiated, directly or indirectly, thus may be abstract. */
   private final Set<DexProgramClass> directAndIndirectlyInstantiatedTypes =
       Sets.newIdentityHashSet();
@@ -299,8 +307,8 @@
   private final Set<DexType> constClassReferences = Sets.newIdentityHashSet();
 
   /**
-   * A map from classes to annotations that need to be processed should the classes ever become
-   * live.
+   * A map from annotation classes to annotations that need to be processed should the classes ever
+   * become live.
    */
   private final Map<DexType, Set<DexAnnotation>> deferredAnnotations = new IdentityHashMap<>();
 
@@ -345,9 +353,7 @@
     }
 
     liveTypes = new SetWithReportedReason<>();
-    liveAnnotations = new SetWithReason<>(graphReporter::registerAnnotation);
     initializedTypes = new SetWithReportedReason<>();
-    instantiatedTypes = new SetWithReason<>(graphReporter::registerClass);
     targetedMethods = new SetWithReason<>(graphReporter::registerMethod);
     // This set is only populated in edge cases due to multiple default interface methods.
     // The set is generally expected to be empty and in the unlikely chance it is not, it will
@@ -359,6 +365,10 @@
     instantiatedInterfaceTypes = Sets.newIdentityHashSet();
     lambdaRewriter = options.desugarState == DesugarState.ON ? new LambdaRewriter(appView) : null;
 
+    // TODO(b/147799448): Enable allocation site tracking during the initial round of tree shaking.
+    objectAllocationInfoCollection =
+        ObjectAllocationInfoCollectionImpl.builder(false, graphReporter);
+
     if (appView.rewritePrefix.isRewriting() && mode.isInitialTreeShaking()) {
       desugaredLibraryWrapperAnalysis = new DesugaredLibraryConversionWrapperAnalysis(appView);
       registerAnalysis(desugaredLibraryWrapperAnalysis);
@@ -409,11 +419,14 @@
         return clazz.asProgramClass();
       }
       if (liveNonProgramTypes.add(clazz) && clazz.isLibraryClass()) {
+        // TODO(b/149201735): This likely needs to apply to classpath too.
         ensureMethodsContinueToWidenAccess(clazz);
+        // TODO(b/149201158): This should apply to classpath too (likely even hard fail).
         warnIfLibraryTypeInheritsFromProgramType(clazz.asLibraryClass());
       }
+    } else {
+      reportMissingClass(type);
     }
-    reportMissingClass(type);
     return null;
   }
 
@@ -453,10 +466,12 @@
     if (item.isDexClass()) {
       DexProgramClass clazz = item.asDexClass().asProgramClass();
       KeepReasonWitness witness = graphReporter.reportKeepClass(precondition, rules, clazz);
-      if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
-        markInterfaceAsInstantiated(clazz, witness);
+      if (clazz.isAnnotation()) {
+        workList.enqueueMarkAnnotationInstantiatedAction(clazz, witness);
+      } else if (clazz.isInterface()) {
+        workList.enqueueMarkInterfaceInstantiatedAction(clazz, witness);
       } else {
-        workList.enqueueMarkInstantiatedAction(clazz, null, witness);
+        workList.enqueueMarkInstantiatedAction(clazz, null, InstantiationReason.KEEP_RULE, witness);
         if (clazz.hasDefaultInitializer()) {
           DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
           if (forceProguardCompatibility) {
@@ -494,9 +509,9 @@
     pinnedItems.add(item.toReference());
   }
 
-  private void markInterfaceAsInstantiated(DexProgramClass clazz, KeepReasonWitness witness) {
-    assert clazz.isInterface() && !clazz.accessFlags.isAnnotation();
-
+  void markInterfaceAsInstantiated(DexProgramClass clazz, KeepReasonWitness witness) {
+    assert !clazz.isAnnotation();
+    assert clazz.isInterface();
     unknownInstantiatedInterfaceTypes.add(clazz, witness);
     if (!instantiatedInterfaceTypes.add(clazz)) {
       return;
@@ -582,7 +597,7 @@
       DexField field, DexEncodedMethod context, boolean isRead, boolean isReflective) {
     FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field);
     if (info == null) {
-      DexEncodedField encodedField = appInfo.resolveField(field);
+      DexEncodedField encodedField = resolveField(field);
 
       // If the field does not exist, then record this in the mapping, such that we don't have to
       // resolve the field the next time.
@@ -761,10 +776,13 @@
       DexProgramClass clazz = getProgramClassOrNull(type);
       if (clazz != null) {
         KeepReason reason = KeepReason.methodHandleReferencedIn(currentMethod);
-        if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
+        if (clazz.isAnnotation()) {
+          markTypeAsLive(clazz, graphReporter.registerClass(clazz, reason));
+        } else if (clazz.isInterface()) {
           markInterfaceAsInstantiated(clazz, graphReporter.registerInterface(clazz, reason));
         } else {
-          markInstantiated(clazz, null, reason);
+          workList.enqueueMarkInstantiatedAction(
+              clazz, null, InstantiationReason.REFERENCED_IN_METHOD_HANDLE, reason);
         }
       }
     }
@@ -951,21 +969,34 @@
       return false;
     }
 
-    return traceNewInstance(type, context, KeepReason.instantiatedIn(currentMethod));
+    return traceNewInstance(
+        type,
+        context,
+        InstantiationReason.NEW_INSTANCE_INSTRUCTION,
+        KeepReason.instantiatedIn(currentMethod));
   }
 
   boolean traceNewInstanceFromLambda(DexType type, ProgramMethod context) {
-    return traceNewInstance(type, context, KeepReason.invokedFromLambdaCreatedIn(context.method));
+    return traceNewInstance(
+        type,
+        context,
+        InstantiationReason.LAMBDA,
+        KeepReason.invokedFromLambdaCreatedIn(context.method));
   }
 
-  private boolean traceNewInstance(DexType type, ProgramMethod context, KeepReason keepReason) {
+  private boolean traceNewInstance(
+      DexType type,
+      ProgramMethod context,
+      InstantiationReason instantiationReason,
+      KeepReason keepReason) {
     DexEncodedMethod currentMethod = context.method;
     DexProgramClass clazz = getProgramClassOrNull(type);
     if (clazz != null) {
-      if (clazz.isInterface()) {
+      if (clazz.isAnnotation() || clazz.isInterface()) {
         markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
       } else {
-        markInstantiated(clazz, currentMethod, keepReason);
+        workList.enqueueMarkInstantiatedAction(
+            clazz, currentMethod, instantiationReason, keepReason);
       }
     }
     return true;
@@ -979,9 +1010,8 @@
     // Must mark the field as targeted even if it does not exist.
     markFieldAsTargeted(field, currentMethod);
 
-    DexEncodedField encodedField = appInfo.resolveField(field);
+    DexEncodedField encodedField = resolveField(field);
     if (encodedField == null) {
-      reportMissingField(field);
       return false;
     }
 
@@ -1016,9 +1046,8 @@
     // Must mark the field as targeted even if it does not exist.
     markFieldAsTargeted(field, currentMethod);
 
-    DexEncodedField encodedField = appInfo.resolveField(field);
+    DexEncodedField encodedField = resolveField(field);
     if (encodedField == null) {
-      reportMissingField(field);
       return false;
     }
 
@@ -1050,11 +1079,10 @@
       return false;
     }
 
-    DexEncodedField encodedField = appInfo.resolveField(field);
+    DexEncodedField encodedField = resolveField(field);
     if (encodedField == null) {
       // Must mark the field as targeted even if it does not exist.
       markFieldAsTargeted(field, currentMethod);
-      reportMissingField(field);
       return false;
     }
 
@@ -1095,11 +1123,10 @@
       return false;
     }
 
-    DexEncodedField encodedField = appInfo.resolveField(field);
+    DexEncodedField encodedField = resolveField(field);
     if (encodedField == null) {
       // Must mark the field as targeted even if it does not exist.
       markFieldAsTargeted(field, currentMethod);
-      reportMissingField(field);
       return false;
     }
 
@@ -1214,7 +1241,7 @@
         reason.apply(holder));
   }
 
-  private void markTypeAsLive(DexProgramClass clazz, KeepReasonWitness witness) {
+  void markTypeAsLive(DexProgramClass clazz, KeepReasonWitness witness) {
     markTypeAsLive(
         clazz,
         scopedMethodsForLiveTypes.computeIfAbsent(clazz.type, ignore -> new ScopedDexMethodSet()),
@@ -1227,6 +1254,13 @@
       return;
     }
 
+    // Mark types in inner-class attributes referenced.
+    InnerClassAttribute innerClassAttributes = holder.getInnerClassAttributeForThisClass();
+    if (innerClassAttributes != null) {
+      recordTypeReference(innerClassAttributes.getInner());
+      recordTypeReference(innerClassAttributes.getOuter());
+    }
+
     if (Log.ENABLED) {
       Log.verbose(getClass(), "Type `%s` has become live.", holder.type);
     }
@@ -1270,15 +1304,15 @@
       enqueueFirstNonSerializableClassInitializer(holder, reason);
     }
 
-    if (!holder.annotations.isEmpty()) {
-      processAnnotations(holder, holder.annotations.annotations);
-    }
+    processAnnotations(holder, holder);
+
     // If this type has deferred annotations, we have to process those now, too.
-    Set<DexAnnotation> annotations = deferredAnnotations.remove(holder.type);
-    if (annotations != null && !annotations.isEmpty()) {
-      assert holder.accessFlags.isAnnotation();
-      assert annotations.stream().allMatch(a -> a.annotation.type == holder.type);
-      annotations.forEach(annotation -> handleAnnotation(holder, annotation));
+    if (holder.isAnnotation()) {
+      Set<DexAnnotation> annotations = deferredAnnotations.remove(holder.type);
+      if (annotations != null && !annotations.isEmpty()) {
+        assert annotations.stream().allMatch(a -> a.annotation.type == holder.type);
+        annotations.forEach(annotation -> processAnnotation(holder, holder, annotation));
+      }
     }
 
     rootSet.forEachDependentStaticMember(holder, appView, this::enqueueDependentItem);
@@ -1335,37 +1369,68 @@
     internalEnqueueRootItem(consequent, reasons, precondition);
   }
 
-  private void processAnnotations(DexDefinition holder, DexAnnotation[] annotations) {
+  private void processAnnotations(DexProgramClass holder, DexDefinition annotatedItem) {
+    processAnnotations(holder, annotatedItem, annotatedItem.annotations());
+  }
+
+  private void processAnnotations(
+      DexProgramClass holder, DexDefinition annotatedItem, DexAnnotationSet annotations) {
+    processAnnotations(holder, annotatedItem, annotations.annotations);
+  }
+
+  private void processAnnotations(
+      DexProgramClass holder, DexDefinition annotatedItem, DexAnnotation[] annotations) {
     for (DexAnnotation annotation : annotations) {
-      processAnnotation(holder, annotation);
+      processAnnotation(holder, annotatedItem, annotation);
     }
   }
 
-  private void processAnnotation(DexDefinition holder, DexAnnotation annotation) {
-    handleAnnotation(holder, annotation);
-  }
-
-  private void handleAnnotation(DexDefinition holder, DexAnnotation annotation) {
+  private void processAnnotation(
+      DexProgramClass holder, DexDefinition annotatedItem, DexAnnotation annotation) {
+    assert annotatedItem == holder
+        || (annotatedItem.isDexEncodedField()
+            && annotatedItem.asDexEncodedField().field.holder == holder.type)
+        || (annotatedItem.isDexEncodedMethod()
+            && annotatedItem.asDexEncodedMethod().method.holder == holder.type);
     assert !holder.isDexClass() || holder.asDexClass().isProgramClass();
     DexType type = annotation.annotation.type;
+    recordTypeReference(type);
     DexClass clazz = appView.definitionFor(type);
     boolean annotationTypeIsLibraryClass = clazz == null || clazz.isNotProgramClass();
     boolean isLive = annotationTypeIsLibraryClass || liveTypes.contains(clazz.asProgramClass());
-    if (!shouldKeepAnnotation(holder, annotation, isLive, appView)) {
+    if (!shouldKeepAnnotation(annotatedItem, annotation, isLive, appView)) {
       // Remember this annotation for later.
       if (!annotationTypeIsLibraryClass) {
         deferredAnnotations.computeIfAbsent(type, ignore -> new HashSet<>()).add(annotation);
       }
       return;
     }
-    KeepReason reason = KeepReason.annotatedOn(holder);
-    liveAnnotations.add(annotation, reason);
+    KeepReason reason = KeepReason.annotatedOn(annotatedItem);
+    graphReporter.registerAnnotation(annotation, reason);
     AnnotationReferenceMarker referenceMarker =
         new AnnotationReferenceMarker(annotation.annotation.type, appView.dexItemFactory(), reason);
     annotation.annotation.collectIndexedItems(referenceMarker);
   }
 
+  private DexEncodedField resolveField(DexField field) {
+    // Record the references in case they are not program types.
+    recordTypeReference(field.holder);
+    recordTypeReference(field.type);
+    DexEncodedField encodedField = appInfo.resolveField(field);
+    if (encodedField == null) {
+      reportMissingField(field);
+      return null;
+    }
+    return encodedField;
+  }
+
   private ResolutionResult resolveMethod(DexMethod method, KeepReason reason) {
+    // Record the references in case they are not program types.
+    recordTypeReference(method.holder);
+    recordTypeReference(method.proto.returnType);
+    for (DexType param : method.proto.parameters.values) {
+      recordTypeReference(param);
+    }
     ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
     if (resolutionResult.isFailedResolution()) {
       reportMissingMethod(method);
@@ -1436,6 +1501,10 @@
     DexType holder = method.holder;
     DexProgramClass clazz = getProgramClassOrNull(holder);
     if (clazz == null) {
+      recordTypeReference(method.proto.returnType);
+      for (DexType param : method.proto.parameters.values) {
+        recordTypeReference(param);
+      }
       return;
     }
     // TODO(zerny): Is it ok that we lookup in both the direct and virtual pool here?
@@ -1496,7 +1565,8 @@
   }
 
   private void reportMissingClass(DexType clazz) {
-    if (Log.ENABLED && reportedMissing.add(clazz)) {
+    boolean newReport = missingTypes.add(clazz);
+    if (Log.ENABLED && newReport) {
       Log.verbose(Enqueuer.class, "Class `%s` is missing.", clazz);
     }
   }
@@ -1521,9 +1591,9 @@
       return;
     }
     markReferencedTypesAsLive(method);
-    processAnnotations(method, method.annotations.annotations);
+    processAnnotations(clazz, method);
     method.parameterAnnotationsList.forEachAnnotation(
-        annotation -> processAnnotation(method, annotation));
+        annotation -> processAnnotation(clazz, method, annotation));
 
     if (Log.ENABLED) {
       Log.verbose(getClass(), "Method `%s` is targeted.", method.method);
@@ -1543,15 +1613,21 @@
    */
   // Package protected due to entry point from worklist.
   void processNewlyInstantiatedClass(
-      DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
-    assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
+      DexProgramClass clazz,
+      DexEncodedMethod context,
+      InstantiationReason instantiationReason,
+      KeepReason keepReason) {
+    assert !clazz.isAnnotation();
+    assert !clazz.isInterface();
+
     // Notify analyses. This is done even if `clazz` has already been marked as instantiated,
     // because each analysis may depend on seeing all the (clazz, reason) pairs. Thus, not doing so
     // could lead to nondeterminism.
     analyses.forEach(
         analysis -> analysis.processNewlyInstantiatedClass(clazz.asProgramClass(), context));
 
-    if (!instantiatedTypes.add(clazz, reason)) {
+    if (!objectAllocationInfoCollection.recordDirectAllocationSite(
+        clazz, context, instantiationReason, keepReason)) {
       return;
     }
 
@@ -1561,7 +1637,7 @@
       Log.verbose(getClass(), "Class `%s` is instantiated, processing...", clazz);
     }
     // This class becomes live, so it and all its supertypes become live types.
-    markTypeAsLive(clazz, graphReporter.registerClass(clazz, reason));
+    markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
     // Instantiation triggers class initialization.
     markDirectAndIndirectClassInitializersAsLive(clazz);
     // For all methods of the class, if we have seen a call, mark the method live.
@@ -1617,7 +1693,7 @@
       transitionReachableVirtualMethods(current, seen);
       Collections.addAll(interfaces, current.interfaces.values);
       current = getProgramClassOrNull(current.superType);
-    } while (current != null && !instantiatedTypes.contains(current));
+    } while (current != null && !objectAllocationInfoCollection.isInstantiatedDirectly(current));
 
     // The set now contains all virtual methods on the type and its supertype that are reachable.
     // In a second step, we now look at interfaces. We have to do this in this order due to JVM
@@ -1673,7 +1749,7 @@
   private void markLibraryAndClasspathMethodOverridesAsLive(
       DexClass libraryClass, DexProgramClass instantiatedClass) {
     assert libraryClass.isNotProgramClass();
-    assert !instantiatedClass.isInterface() || instantiatedClass.accessFlags.isAnnotation();
+    assert !instantiatedClass.isInterface() || instantiatedClass.isAnnotation();
     for (DexEncodedMethod method : libraryClass.virtualMethods()) {
       // Note: it may be worthwhile to add a resolution cache here. If so, it must still ensure
       // that all library override edges are reported to the kept-graph consumer.
@@ -1775,24 +1851,26 @@
       if (reachableFields != null) {
         for (DexEncodedField field : reachableFields.getItems()) {
           // TODO(b/120959039): Should the reason this field is reachable come from the set?
-          markInstanceFieldAsLive(field, KeepReason.reachableFromLiveType(clazz.type));
+          markInstanceFieldAsLive(clazz, field, KeepReason.reachableFromLiveType(clazz.type));
         }
       }
       clazz = getProgramClassOrNull(clazz.superType);
-    } while (clazz != null && !instantiatedTypes.contains(clazz));
+    } while (clazz != null && !objectAllocationInfoCollection.isInstantiatedDirectly(clazz));
   }
 
-  private void transitionDependentItemsForInstantiatedClass(DexClass clazz) {
-    DexClass current = clazz;
+  private void transitionDependentItemsForInstantiatedClass(DexProgramClass clazz) {
+    assert !clazz.isAnnotation();
+    assert !clazz.isInterface();
     do {
       // Handle keep rules that are dependent on the class being instantiated.
-      rootSet.forEachDependentNonStaticMember(current, appView, this::enqueueDependentItem);
+      rootSet.forEachDependentNonStaticMember(clazz, appView, this::enqueueDependentItem);
 
       // Visit the super type.
-      current = current.superType != null ? appView.definitionFor(current.superType) : null;
-    } while (current != null
-        && current.isProgramClass()
-        && !instantiatedTypes.contains(current.asProgramClass()));
+      clazz =
+          clazz.superType != null
+              ? asProgramClassOrNull(appView.definitionFor(clazz.superType))
+              : null;
+    } while (clazz != null && !objectAllocationInfoCollection.isInstantiatedDirectly(clazz));
   }
 
   private void transitionUnusedInterfaceToLive(DexProgramClass clazz) {
@@ -1841,7 +1919,7 @@
             encodedField.field);
       }
     }
-    processAnnotations(encodedField, encodedField.annotations.annotations);
+    processAnnotations(clazz, encodedField);
     liveFields.add(encodedField, reason);
 
     // Add all dependent members to the workqueue.
@@ -1851,7 +1929,8 @@
     analyses.forEach(analysis -> analysis.processNewlyLiveField(encodedField));
   }
 
-  private void markInstanceFieldAsLive(DexEncodedField field, KeepReason reason) {
+  private void markInstanceFieldAsLive(
+      DexProgramClass holder, DexEncodedField field, KeepReason reason) {
     assert field != null;
     assert field.isProgramField(appView);
     markTypeAsLive(field.field.holder, reason);
@@ -1859,7 +1938,7 @@
     if (Log.ENABLED) {
       Log.verbose(getClass(), "Adding instance field `%s` to live set.", field.field);
     }
-    processAnnotations(field, field.annotations.annotations);
+    processAnnotations(holder, field);
     liveFields.add(field, reason);
 
     // Add all dependent members to the workqueue.
@@ -1869,14 +1948,6 @@
     analyses.forEach(analysis -> analysis.processNewlyLiveField(field));
   }
 
-  private void markInstantiated(
-      DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
-    if (Log.ENABLED) {
-      Log.verbose(getClass(), "Register new instantiation of `%s`.", clazz);
-    }
-    workList.enqueueMarkInstantiatedAction(clazz, context, reason);
-  }
-
   private void markLambdaInstantiated(DexType itf, DexEncodedMethod method) {
     DexClass clazz = appView.definitionFor(itf);
     if (clazz == null) {
@@ -1998,7 +2069,7 @@
       markStaticFieldAsLive(encodedField, reason);
     } else {
       if (isInstantiatedOrHasInstantiatedSubtype(clazz)) {
-        markInstanceFieldAsLive(encodedField, reason);
+        markInstanceFieldAsLive(clazz, encodedField, reason);
       } else {
         // Add the field to the reachable set if the type later becomes instantiated.
         reachableInstanceFields
@@ -2008,6 +2079,19 @@
     }
   }
 
+  private void recordTypeReference(DexType type) {
+    if (type == null) {
+      return;
+    }
+    if (type.isArrayType()) {
+      type = type.toBaseType(appView.dexItemFactory());
+    }
+    if (!type.isClassType()) {
+      return;
+    }
+    getProgramClassOrNull(type);
+  }
+
   private void markVirtualMethodAsReachable(
       DexMethod method, boolean interfaceInvoke, ProgramMethod contextOrNull, KeepReason reason) {
     if (method.holder.isArrayType()) {
@@ -2024,6 +2108,12 @@
     // TODO(b/70160030): Revise this to support tree shaking library methods on non-escaping types.
     DexProgramClass holder = getProgramClassOrNull(method.holder);
     if (holder == null) {
+      // TODO(b/139464956): clean this.
+      // Ensure that the full proto of the targeted method is referenced.
+      recordTypeReference(method.proto.returnType);
+      for (DexType type : method.proto.parameters.values) {
+        recordTypeReference(type);
+      }
       return;
     }
 
@@ -2065,14 +2155,15 @@
     assert resolution.holder.isProgramClass();
 
     assert interfaceInvoke == holder.isInterface();
-    Set<DexEncodedMethod> possibleTargets =
+    LookupResult lookupResult =
         // TODO(b/140214802): Call on the resolution once proper resolution and lookup is resolved.
         new SingleResolutionResult(holder, resolution.holder, resolution.method)
-            .lookupVirtualDispatchTargets(appInfo);
-    if (possibleTargets == null || possibleTargets.isEmpty()) {
+            .lookupVirtualDispatchTargets(appView, appInfo);
+    if (!lookupResult.isLookupResultSuccess()) {
       return;
     }
-    for (DexEncodedMethod encodedPossibleTarget : possibleTargets) {
+    for (DexEncodedMethod encodedPossibleTarget :
+        lookupResult.asLookupResultSuccess().getMethodTargets()) {
       if (encodedPossibleTarget.isAbstract()) {
         continue;
       }
@@ -2104,7 +2195,8 @@
       return;
     }
 
-    if (instantiatedTypes.contains(clazz) || instantiatedInterfaceTypes.contains(clazz)) {
+    if (objectAllocationInfoCollection.isInstantiatedDirectly(clazz)
+        || instantiatedInterfaceTypes.contains(clazz)) {
       markVirtualMethodAsLive(
           clazz,
           encodedPossibleTarget,
@@ -2120,7 +2212,7 @@
         if (currentClass == null || currentClass.lookupVirtualMethod(possibleTarget) != null) {
           continue;
         }
-        if (instantiatedTypes.contains(currentClass)
+        if (objectAllocationInfoCollection.isInstantiatedDirectly(currentClass)
             || instantiatedInterfaceTypes.contains(currentClass)) {
           markVirtualMethodAsLive(
               clazz,
@@ -2313,10 +2405,6 @@
   }
 
   private AppInfoWithLiveness createAppInfo(AppInfoWithSubtyping appInfo) {
-    ImmutableSortedSet.Builder<DexType> builder =
-        ImmutableSortedSet.orderedBy(PresortedComparable::slowCompareTo);
-    liveAnnotations.items.forEach(annotation -> builder.add(annotation.annotation.type));
-
     // Remove the temporary mappings that have been inserted into the field access info collection
     // and verify that the mapping is then one-to-one.
     fieldAccessInfoCollection.removeIf(
@@ -2330,9 +2418,39 @@
       liveMethods.add(bridge.holder, bridge.method, graphReporter.fakeReportShouldNotBeUsed());
     }
 
-    // A direct appInfo is required to add classpath classes in wrapper post processing.
-    assert appInfo.app().isDirect() : "Expected a direct appInfo after enqueuing.";
-    DirectMappedDexApplication.Builder appBuilder = appInfo.app().asDirect().builder();
+    // Ensure references from various root set collections.
+    rootSet
+        .noSideEffects
+        .keySet()
+        .forEach(
+            r -> {
+              if (r.isDexType()) {
+                recordTypeReference(r.asDexType());
+              } else if (r.isDexField()) {
+                recordTypeReference(r.asDexField().holder);
+                recordTypeReference(r.asDexField().type);
+              } else {
+                assert r.isDexMethod();
+                recordTypeReference(r.asDexMethod().holder);
+                recordTypeReference(r.asDexMethod().proto.returnType);
+                for (DexType param : r.asDexMethod().proto.parameters.values) {
+                  recordTypeReference(param);
+                }
+              }
+            });
+
+    // Rebuild a new app only containing referenced types.
+    appView.dexItemFactory().forEachPossiblyCompilerSynthesizedType(this::recordTypeReference);
+    Set<DexLibraryClass> libraryClasses = Sets.newIdentityHashSet();
+    Set<DexClasspathClass> classpathClasses = Sets.newIdentityHashSet();
+    for (DexClass clazz : liveNonProgramTypes) {
+      traverseHierarchy(clazz, libraryClasses, classpathClasses);
+    }
+    Builder appBuilder = appInfo.app().asDirect().builder();
+    appBuilder.replaceLibraryClasses(libraryClasses);
+    appBuilder.replaceClasspathClasses(classpathClasses);
+    // Can't replace the program classes at this point as they are needed in tree pruning.
+    // Post process the app to add synthetic content.
     postProcessLambdaDesugaring(appBuilder);
     postProcessLibraryConversionWrappers(appBuilder);
     DirectMappedDexApplication app = appBuilder.build();
@@ -2340,11 +2458,9 @@
     AppInfoWithLiveness appInfoWithLiveness =
         new AppInfoWithLiveness(
             app,
+            missingTypes,
             SetUtils.mapIdentityHashSet(liveTypes.getItems(), DexProgramClass::getType),
-            SetUtils.mapIdentityHashSet(
-                liveAnnotations.getItems(), DexAnnotation::getAnnotationType),
             Collections.unmodifiableSet(instantiatedAppServices),
-            SetUtils.mapIdentityHashSet(instantiatedTypes.getItems(), DexProgramClass::getType),
             Enqueuer.toSortedDescriptorSet(targetedMethods.getItems()),
             Collections.unmodifiableSet(failedResolutionTargets),
             ImmutableSortedSet.copyOf(DexMethod::slowCompareTo, bootstrapMethods),
@@ -2354,6 +2470,7 @@
             toSortedDescriptorSet(liveMethods.getItems()),
             // Filter out library fields and pinned fields, because these are read by default.
             fieldAccessInfoCollection,
+            objectAllocationInfoCollection.build(),
             // TODO(b/132593519): Do we require these sets to be sorted for determinism?
             toImmutableSortedMap(virtualInvokes, PresortedComparable::slowCompare),
             toImmutableSortedMap(interfaceInvokes, PresortedComparable::slowCompare),
@@ -2388,6 +2505,46 @@
     return appInfoWithLiveness;
   }
 
+  private void traverseHierarchy(
+      DexClass clazz,
+      Set<DexLibraryClass> libraryClasses,
+      Set<DexClasspathClass> classpathClasses) {
+    if (clazz.isLibraryClass()) {
+      libraryClasses.add(clazz.asLibraryClass());
+    } else if (clazz.isClasspathClass()) {
+      classpathClasses.add(clazz.asClasspathClass());
+    }
+    Deque<DexType> worklist = new ArrayDeque<>();
+    if (clazz.superType != null) {
+      worklist.add(clazz.superType);
+    }
+    Collections.addAll(worklist, clazz.interfaces.values);
+    while (!worklist.isEmpty()) {
+      DexType type = worklist.pop();
+      DexClass definition = appView.definitionFor(type);
+      if (definition == null) {
+        continue;
+      }
+      if (definition.isProgramClass()) {
+        // TODO(b/120884788): This should assert not possible once fixed.
+        continue;
+      }
+      if (definition.isLibraryClass()) {
+        if (!libraryClasses.add(definition.asLibraryClass())) {
+          continue;
+        }
+      } else if (definition.isClasspathClass()) {
+        if (!classpathClasses.add(definition.asClasspathClass())) {
+          continue;
+        }
+      }
+      if (definition.superType != null) {
+        worklist.add(definition.superType);
+      }
+      Collections.addAll(worklist, definition.interfaces.values);
+    }
+  }
+
   private void postProcessLibraryConversionWrappers(DirectMappedDexApplication.Builder appBuilder) {
     if (desugaredLibraryWrapperAnalysis == null) {
       return;
@@ -2406,7 +2563,11 @@
     for (DexProgramClass wrapper : wrappers) {
       appBuilder.addProgramClass(wrapper);
       liveTypes.add(wrapper, graphReporter.fakeReportShouldNotBeUsed());
-      instantiatedTypes.add(wrapper, graphReporter.fakeReportShouldNotBeUsed());
+      objectAllocationInfoCollection.recordDirectAllocationSite(
+          wrapper,
+          null,
+          InstantiationReason.SYNTHESIZED_CLASS,
+          graphReporter.fakeReportShouldNotBeUsed());
       // Mark all methods on the wrapper as live and targeted.
       for (DexEncodedMethod method : wrapper.methods()) {
         targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
@@ -2441,7 +2602,11 @@
         appBuilder.addToMainDexList(Collections.singletonList(programClass.type));
       }
       liveTypes.add(programClass, graphReporter.fakeReportShouldNotBeUsed());
-      instantiatedTypes.add(programClass, graphReporter.fakeReportShouldNotBeUsed());
+      objectAllocationInfoCollection.recordDirectAllocationSite(
+          programClass,
+          null,
+          InstantiationReason.SYNTHESIZED_CLASS,
+          graphReporter.fakeReportShouldNotBeUsed());
 
       // Register all of the field writes in the lambda constructors.
       // This is needed to ensure that the initializers can be optimized.
@@ -2529,10 +2694,10 @@
   }
 
   private static <T extends PresortedComparable<T>> SortedSet<T> toSortedDescriptorSet(
-      Set<? extends KeyedDexItem<T>> set) {
+      Set<? extends DexEncodedMember<T>> set) {
     ImmutableSortedSet.Builder<T> builder =
         new ImmutableSortedSet.Builder<>(PresortedComparable::slowCompareTo);
-    for (KeyedDexItem<T> item : set) {
+    for (DexEncodedMember<T> item : set) {
       builder.add(item.getKey());
     }
     return builder.build();
@@ -2554,19 +2719,15 @@
     timing.begin("Grow the tree.");
     try {
       while (true) {
-        long numOfLiveItems = (long) liveTypes.items.size();
-        numOfLiveItems += (long) liveMethods.items.size();
-        numOfLiveItems += (long) liveFields.items.size();
+        long numberOfLiveItems = getNumberOfLiveItems();
         while (!workList.isEmpty()) {
           EnqueuerAction action = workList.poll();
           action.run(this);
         }
 
         // Continue fix-point processing if -if rules are enabled by items that newly became live.
-        long numOfLiveItemsAfterProcessing = (long) liveTypes.items.size();
-        numOfLiveItemsAfterProcessing += (long) liveMethods.items.size();
-        numOfLiveItemsAfterProcessing += (long) liveFields.items.size();
-        if (numOfLiveItemsAfterProcessing > numOfLiveItems) {
+        long numberOfLiveItemsAfterProcessing = getNumberOfLiveItems();
+        if (numberOfLiveItemsAfterProcessing > numberOfLiveItems) {
           // Build the mapping of active if rules. We use a single collection of if-rules to allow
           // removing if rules that have a constant sequent keep rule when they materialize.
           if (activeIfRules == null) {
@@ -2590,6 +2751,7 @@
                   consequentSetBuilder,
                   targetedMethods.getItems());
           addConsequentRootSet(ifRuleEvaluator.run(), false);
+          assert getNumberOfLiveItems() == numberOfLiveItemsAfterProcessing;
           if (!workList.isEmpty()) {
             continue;
           }
@@ -2631,11 +2793,6 @@
         Set<DexEncodedMethod> reachableNotLive = Sets.difference(allLive, liveMethods.getItems());
         Log.debug(getClass(), "%s methods are reachable but not live", reachableNotLive.size());
         Log.info(getClass(), "Only reachable: %s", reachableNotLive);
-        Set<DexProgramClass> liveButNotInstantiated =
-            Sets.difference(liveTypes.getItems(), instantiatedTypes.getItems());
-        Log.debug(getClass(), "%s classes are live but not instantiated",
-            liveButNotInstantiated.size());
-        Log.info(getClass(), "Live but not instantiated: %s", liveButNotInstantiated);
         SetView<DexEncodedMethod> targetedButNotLive = Sets
             .difference(targetedMethods.getItems(), liveMethods.getItems());
         Log.debug(getClass(), "%s methods are targeted but not live", targetedButNotLive.size());
@@ -2647,6 +2804,13 @@
     unpinLambdaMethods();
   }
 
+  private long getNumberOfLiveItems() {
+    long result = liveTypes.items.size();
+    result += liveMethods.items.size();
+    result += liveFields.items.size();
+    return result;
+  }
+
   private void addConsequentRootSet(ConsequentRootSet consequentRootSet, boolean addNoShrinking) {
     // TODO(b/132600955): This modifies the root set. Should the consequent be persistent?
     rootSet.addConsequentRootSet(consequentRootSet, addNoShrinking);
@@ -2835,9 +2999,9 @@
       }
     }
     markParameterAndReturnTypesAsLive(method);
-    processAnnotations(method, method.annotations.annotations);
+    processAnnotations(clazz, method);
     method.parameterAnnotationsList.forEachAnnotation(
-        annotation -> processAnnotation(method, annotation));
+        annotation -> processAnnotation(clazz, method, annotation));
     method.registerCodeReferences(useRegistryFactory.create(appView, clazz, method, this));
 
     // Add all dependent members to the workqueue.
@@ -2865,7 +3029,7 @@
   }
 
   private void markClassAsInstantiatedWithReason(DexProgramClass clazz, KeepReason reason) {
-    workList.enqueueMarkInstantiatedAction(clazz, null, reason);
+    workList.enqueueMarkInstantiatedAction(clazz, null, InstantiationReason.REFLECTION, reason);
     if (clazz.hasDefaultInitializer()) {
       workList.enqueueMarkReachableDirectAction(clazz.getDefaultInitializer().method, reason);
     }
@@ -2873,16 +3037,18 @@
 
   private void markClassAsInstantiatedWithCompatRule(
       DexProgramClass clazz, KeepReasonWitness witness) {
-    if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
+    if (clazz.isAnnotation()) {
+      markTypeAsLive(clazz, witness);
+    } else if (clazz.isInterface()) {
       markInterfaceAsInstantiated(clazz, witness);
-      return;
-    }
-    workList.enqueueMarkInstantiatedAction(clazz, null, witness);
-    if (clazz.hasDefaultInitializer()) {
-      DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
-      workList.enqueueMarkReachableDirectAction(
-          defaultInitializer.method,
-          graphReporter.reportCompatKeepDefaultInitializer(clazz, defaultInitializer));
+    } else {
+      workList.enqueueMarkInstantiatedAction(clazz, null, InstantiationReason.KEEP_RULE, witness);
+      if (clazz.hasDefaultInitializer()) {
+        DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
+        workList.enqueueMarkReachableDirectAction(
+            defaultInitializer.method,
+            graphReporter.reportCompatKeepDefaultInitializer(clazz, defaultInitializer));
+      }
     }
   }
 
@@ -2940,10 +3106,11 @@
       if (clazz == null) {
         return;
       }
-      if (clazz.isInterface()) {
+      if (clazz.isAnnotation() || clazz.isInterface()) {
         markTypeAsLive(clazz.type, KeepReason.reflectiveUseIn(method));
       } else {
-        markInstantiated(clazz, null, KeepReason.reflectiveUseIn(method));
+        workList.enqueueMarkInstantiatedAction(
+            clazz, null, InstantiationReason.REFLECTION, KeepReason.reflectiveUseIn(method));
         if (clazz.hasDefaultInitializer()) {
           DexEncodedMethod initializer = clazz.getDefaultInitializer();
           KeepReason reason = KeepReason.reflectiveUseIn(method);
@@ -2970,7 +3137,8 @@
           !encodedField.accessFlags.isStatic()
               && dexItemFactory.atomicFieldUpdaterMethods.isFieldUpdater(invokedMethod);
       if (keepClass) {
-        markInstantiated(clazz, null, KeepReason.reflectiveUseIn(method));
+        workList.enqueueMarkInstantiatedAction(
+            clazz, null, InstantiationReason.REFLECTION, KeepReason.reflectiveUseIn(method));
       }
       if (pinnedItems.add(encodedField.field)) {
         markFieldAsKept(clazz, encodedField, KeepReason.reflectiveUseIn(method));
@@ -3428,6 +3596,8 @@
 
     @Override
     public boolean addField(DexField field) {
+      recordTypeReference(field.holder);
+      recordTypeReference(field.type);
       DexClass holder = appView.definitionFor(field.holder);
       if (holder == null) {
         return false;
@@ -3462,6 +3632,11 @@
 
     @Override
     public boolean addMethod(DexMethod method) {
+      // Record the references in case they are not program types.
+      recordTypeReference(method.proto.returnType);
+      for (DexType param : method.proto.parameters.values) {
+        recordTypeReference(param);
+      }
       DexProgramClass holder = getProgramClassOrNull(method.holder);
       if (holder == null) {
         return false;
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index d98d7c9..45e61a4 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -68,20 +68,56 @@
   }
 
   static class MarkInstantiatedAction extends EnqueuerAction {
+
     final DexProgramClass target;
     final DexEncodedMethod context;
-    final KeepReason reason;
+    final InstantiationReason instantiationReason;
+    final KeepReason keepReason;
 
     public MarkInstantiatedAction(
-        DexProgramClass target, DexEncodedMethod context, KeepReason reason) {
+        DexProgramClass target,
+        DexEncodedMethod context,
+        InstantiationReason instantiationReason,
+        KeepReason keepReason) {
       this.target = target;
       this.context = context;
+      this.instantiationReason = instantiationReason;
+      this.keepReason = keepReason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.processNewlyInstantiatedClass(target, context, instantiationReason, keepReason);
+    }
+  }
+
+  static class MarkAnnotationInstantiatedAction extends EnqueuerAction {
+    final DexProgramClass target;
+    final KeepReasonWitness reason;
+
+    public MarkAnnotationInstantiatedAction(DexProgramClass target, KeepReasonWitness reason) {
+      this.target = target;
       this.reason = reason;
     }
 
     @Override
     public void run(Enqueuer enqueuer) {
-      enqueuer.processNewlyInstantiatedClass(target, context, reason);
+      enqueuer.markTypeAsLive(target, reason);
+    }
+  }
+
+  static class MarkInterfaceInstantiatedAction extends EnqueuerAction {
+    final DexProgramClass target;
+    final KeepReasonWitness reason;
+
+    public MarkInterfaceInstantiatedAction(DexProgramClass target, KeepReasonWitness reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markInterfaceAsInstantiated(target, reason);
     }
   }
 
@@ -235,9 +271,25 @@
   // TODO(b/142378367): Context is the containing method that is cause of the instantiation.
   // Consider updating call sites with the context information to increase precision where possible.
   void enqueueMarkInstantiatedAction(
-      DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
-    assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
-    queue.add(new MarkInstantiatedAction(clazz, context, reason));
+      DexProgramClass clazz,
+      DexEncodedMethod context,
+      InstantiationReason instantiationReason,
+      KeepReason keepReason) {
+    assert !clazz.isAnnotation();
+    assert !clazz.isInterface();
+    queue.add(new MarkInstantiatedAction(clazz, context, instantiationReason, keepReason));
+  }
+
+  void enqueueMarkAnnotationInstantiatedAction(DexProgramClass clazz, KeepReasonWitness reason) {
+    assert clazz.isAnnotation();
+    assert clazz.isInterface();
+    queue.add(new MarkAnnotationInstantiatedAction(clazz, reason));
+  }
+
+  void enqueueMarkInterfaceInstantiatedAction(DexProgramClass clazz, KeepReasonWitness reason) {
+    assert !clazz.isAnnotation();
+    assert clazz.isInterface();
+    queue.add(new MarkInterfaceInstantiatedAction(clazz, reason));
   }
 
   void enqueueMarkMethodLiveAction(
diff --git a/src/main/java/com/android/tools/r8/shaking/InstantiationReason.java b/src/main/java/com/android/tools/r8/shaking/InstantiationReason.java
new file mode 100644
index 0000000..c6af09d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/InstantiationReason.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, 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.shaking;
+
+public enum InstantiationReason {
+  KEEP_RULE,
+  LAMBDA,
+  NEW_INSTANCE_INSTRUCTION,
+  REFERENCED_IN_METHOD_HANDLE,
+  REFLECTION,
+  SYNTHESIZED_CLASS
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
index 47cc590..3a6fcae 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
@@ -43,7 +43,7 @@
       assert clazz != null;
       consumer.accept(type);
       // Super and interfaces are live, no need to add them.
-      traceAnnotationsDirectDependencies(clazz.annotations);
+      traceAnnotationsDirectDependencies(clazz.annotations());
       clazz.forEachField(field -> consumer.accept(field.field.type));
       clazz.forEachMethod(method -> {
         traceMethodDirectDependencies(method.method, consumer);
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
index 718b9a9..b92f82e 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.shaking;
 
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexClass;
@@ -13,7 +14,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
 import com.android.tools.r8.utils.SetUtils;
-import com.google.common.collect.Maps;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -32,16 +33,7 @@
   private final DirectMappedDexApplication dexApplication;
   private final MainDexClasses.Builder mainDexClassesBuilder;
 
-  /**
-   * @param roots Classes which code may be executed before secondary dex files loading.
-   * @param application the dex appplication.
-   */
-  public MainDexListBuilder(Set<DexProgramClass> roots, DirectMappedDexApplication application) {
-    this.dexApplication = application;
-    this.appInfo = new AppInfoWithSubtyping(dexApplication);
-    // Only consider program classes for the root set.
-    this.roots = SetUtils.mapIdentityHashSet(roots, DexProgramClass::getType);
-    mainDexClassesBuilder = MainDexClasses.builder(appInfo).addRoots(this.roots);
+  public static void checkForAssumedLibraryTypes(AppInfo appInfo) {
     DexClass enumType = appInfo.definitionFor(appInfo.dexItemFactory().enumType);
     if (enumType == null) {
       throw new CompilationError("Tracing for legacy multi dex is not possible without all"
@@ -52,9 +44,19 @@
       throw new CompilationError("Tracing for legacy multi dex is not possible without all"
           + " classpath libraries (java.lang.annotation.Annotation is missing)");
     }
-    annotationTypeContainEnum =
-        Maps.newHashMapWithExpectedSize(
-            appInfo.subtypes(appInfo.dexItemFactory().annotationType).size());
+  }
+
+  /**
+   * @param roots Classes which code may be executed before secondary dex files loading.
+   * @param application the dex appplication.
+   */
+  public MainDexListBuilder(Set<DexProgramClass> roots, DirectMappedDexApplication application) {
+    this.dexApplication = application;
+    this.appInfo = new AppInfoWithSubtyping(dexApplication);
+    // Only consider program classes for the root set.
+    this.roots = SetUtils.mapIdentityHashSet(roots, DexProgramClass::getType);
+    mainDexClassesBuilder = MainDexClasses.builder(appInfo).addRoots(this.roots);
+    annotationTypeContainEnum = new IdentityHashMap<>();
   }
 
   public MainDexClasses run() {
@@ -126,11 +128,6 @@
     return appInfo.isSubtype(valueType, appInfo.dexItemFactory().annotationType);
   }
 
-  private boolean isProgramClass(DexType dexType) {
-    DexClass clazz = appInfo.definitionFor(dexType);
-    return clazz != null && clazz.isProgramClass();
-  }
-
   private void traceMainDexDirectDependencies() {
     new MainDexDirectReferenceTracer(appInfo, this::addDirectDependency)
         .run(roots);
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
index c5dcb0c..f75a307 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
@@ -105,7 +105,7 @@
         .setClassType(ProguardClassType.CLASS)
         .setClassNames(
             ProguardClassNameList.singletonList(
-                ProguardTypeMatcher.create(factory.createType("Landroid/os/Build$VERSION;"))))
+                ProguardTypeMatcher.create(factory.androidOsBuildVersionType)))
         .setMemberRules(
             ImmutableList.of(
                 ProguardMemberRule.builder()
@@ -138,7 +138,7 @@
           && !rule.getInheritanceClassName().matches(factory.objectType)) {
         continue;
       }
-      if (!rule.getClassNames().matches(factory.createType("Landroid/os/Build$VERSION;"))) {
+      if (!rule.getClassNames().matches(factory.androidOsBuildVersionType)) {
         continue;
       }
       for (ProguardMemberRule memberRule : rule.getMemberRules()) {
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 4186091..7495c6b 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -871,11 +871,11 @@
   }
 
   static boolean containsAnnotation(ProguardTypeMatcher classAnnotation, DexClass clazz) {
-    return containsAnnotation(classAnnotation, clazz.annotations);
+    return containsAnnotation(classAnnotation, clazz.annotations());
   }
 
   static boolean containsAnnotation(ProguardTypeMatcher classAnnotation, DexEncodedMethod method) {
-    if (containsAnnotation(classAnnotation, method.annotations)) {
+    if (containsAnnotation(classAnnotation, method.annotations())) {
       return true;
     }
     for (int i = 0; i < method.parameterAnnotationsList.size(); i++) {
@@ -887,7 +887,7 @@
   }
 
   static boolean containsAnnotation(ProguardTypeMatcher classAnnotation, DexEncodedField field) {
-    return containsAnnotation(classAnnotation, field.annotations);
+    return containsAnnotation(classAnnotation, field.annotations());
   }
 
   private static boolean containsAnnotation(
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index dc66249..3ded35c 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
@@ -15,7 +16,6 @@
 import com.android.tools.r8.graph.DirectMappedDexApplication;
 import com.android.tools.r8.graph.EnclosingMethodAttribute;
 import com.android.tools.r8.graph.InnerClassAttribute;
-import com.android.tools.r8.graph.KeyedDexItem;
 import com.android.tools.r8.graph.NestMemberClassAttribute;
 import com.android.tools.r8.graph.PresortedComparable;
 import com.android.tools.r8.logging.Log;
@@ -85,7 +85,7 @@
       }
       if (appInfo.isLiveProgramClass(clazz)) {
         newClasses.add(clazz);
-        if (!appInfo.instantiatedTypes.contains(clazz.type)
+        if (!appInfo.getObjectAllocationInfoCollection().isInstantiatedDirectly(clazz)
             && !options.forceProguardCompatibility) {
           // The class is only needed as a type but never instantiated. Make it abstract to reflect
           // this.
@@ -243,8 +243,8 @@
     return context == null || !isTypeLive(context);
   }
 
-  private <S extends PresortedComparable<S>, T extends KeyedDexItem<S>> int firstUnreachableIndex(
-      List<T> items, Predicate<T> live) {
+  private <S extends PresortedComparable<S>, T extends DexEncodedMember<S>>
+      int firstUnreachableIndex(List<T> items, Predicate<T> live) {
     for (int i = 0; i < items.size(); i++) {
       if (!live.test(items.get(i))) {
         return i;
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 8217920..76db9fe 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.DexClass.FieldSetter;
 import com.android.tools.r8.graph.DexClass.MethodSetter;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
@@ -26,7 +27,7 @@
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.GraphLense.GraphLenseLookupResult;
-import com.android.tools.r8.graph.KeyedDexItem;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
 import com.android.tools.r8.graph.PresortedComparable;
@@ -325,7 +326,7 @@
   // Returns true if [clazz] is a merge candidate. Note that the result of the checks in this
   // method do not change in response to any class merges.
   private boolean isMergeCandidate(DexProgramClass clazz, Set<DexType> pinnedTypes) {
-    if (appInfo.instantiatedTypes.contains(clazz.type)
+    if (appInfo.getObjectAllocationInfoCollection().isInstantiatedDirectly(clazz)
         || appInfo.instantiatedLambdas.contains(clazz.type)
         || appInfo.isPinned(clazz.type)
         || pinnedTypes.contains(clazz.type)
@@ -334,7 +335,7 @@
     }
 
     assert Streams.stream(Iterables.concat(clazz.fields(), clazz.methods()))
-        .map(KeyedDexItem::getKey)
+        .map(DexEncodedMember::getKey)
         .noneMatch(appInfo::isPinned);
 
     if (appView.options().featureSplitConfiguration != null &&
@@ -734,11 +735,17 @@
       //   }
       for (DexEncodedMethod method : defaultMethods) {
         // Conservatively find all possible targets for this method.
-        Set<DexEncodedMethod> interfaceTargets =
+        LookupResult lookupResult =
             appInfo
                 .resolveMethodOnInterface(method.method.holder, method.method)
-                .lookupVirtualDispatchTargets(appInfo);
-
+                .lookupVirtualDispatchTargets(appView, appInfo);
+        assert lookupResult.isLookupResultSuccess();
+        if (lookupResult.isLookupResultFailure()) {
+          return true;
+        }
+        assert lookupResult.isLookupResultSuccess();
+        Set<DexEncodedMethod> interfaceTargets =
+            lookupResult.asLookupResultSuccess().getMethodTargets();
         // If [method] is not even an interface-target, then we can safely merge it. Otherwise we
         // need to check for a conflict.
         if (interfaceTargets.remove(method)) {
@@ -1262,12 +1269,12 @@
       return null;
     }
 
-    private <T extends KeyedDexItem<S>, S extends PresortedComparable<S>> void add(
+    private <T extends DexEncodedMember<S>, S extends PresortedComparable<S>> void add(
         Map<Wrapper<S>, T> map, T item, Equivalence<S> equivalence) {
       map.put(equivalence.wrap(item.getKey()), item);
     }
 
-    private <T extends KeyedDexItem<S>, S extends PresortedComparable<S>> void addAll(
+    private <T extends DexEncodedMember<S>, S extends PresortedComparable<S>> void addAll(
         Collection<Wrapper<S>> collection, Iterable<T> items, Equivalence<S> equivalence) {
       for (T item : items) {
         collection.add(equivalence.wrap(item.getKey()));
diff --git a/src/main/java/com/android/tools/r8/utils/LensUtils.java b/src/main/java/com/android/tools/r8/utils/LensUtils.java
new file mode 100644
index 0000000..325d6fa
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/LensUtils.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, 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.utils;
+
+import com.android.tools.r8.graph.DexDefinitionSupplier;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.GraphLense;
+import com.google.common.collect.Sets;
+import java.util.Set;
+
+public class LensUtils {
+
+  public static Set<DexEncodedMethod> rewrittenWithRenamedSignature(
+      Set<DexEncodedMethod> methods, DexDefinitionSupplier definitions, GraphLense lens) {
+    Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
+    for (DexEncodedMethod method : methods) {
+      result.add(lens.mapDexEncodedMethod(method, definitions));
+    }
+    return result;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 7bcf1c9..78edccb 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -35,6 +35,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser;
 import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser.Result;
@@ -46,6 +47,7 @@
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.naming.Range;
+import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.google.common.base.Suppliers;
 import java.util.ArrayList;
@@ -306,6 +308,7 @@
           // methods, we either did not rename them, we renamed them according to a supplied map or
           // they may be bridges for interface methods with covariant return types.
           sortMethods(methods);
+          assert verifyMethodsAreKeptDirectlyOrIndirectly(appView, methods);
         }
 
         boolean identityMapping =
@@ -431,6 +434,43 @@
     return classNameMapperBuilder.build();
   }
 
+  private static boolean verifyMethodsAreKeptDirectlyOrIndirectly(
+      AppView<AppInfoWithSubtyping> appView, List<DexEncodedMethod> methods) {
+    if (appView.options().isGeneratingClassFiles()) {
+      return true;
+    }
+    RootSet rootSet = appView.rootSet();
+    DexString originalName = null;
+    for (DexEncodedMethod method : methods) {
+      // We cannot rename instance initializers.
+      if (method.isInstanceInitializer()) {
+        continue;
+      }
+      // If the method is pinned, we cannot minify it.
+      if (rootSet.mayNotBeMinified(method.method, appView)) {
+        continue;
+      }
+      // With desugared library, call-backs names are reserved here.
+      if (method.isLibraryMethodOverride().isTrue()) {
+        continue;
+      }
+      // We use the same name for interface names even if it has different types.
+      DexProgramClass clazz = appView.definitionForProgramType(method.method.holder);
+      ResolutionResult resolutionResult =
+          appView.appInfo().resolveMaximallySpecificMethods(clazz, method.method);
+      if (resolutionResult.isFailedResolution()) {
+        // We cannot rename methods we cannot look up.
+        continue;
+      }
+      String errorString = method.method.qualifiedName() + " is not kept but is overloaded";
+      assert resolutionResult.isSingleResolution() : errorString;
+      assert resolutionResult.asSingleResolution().getResolvedHolder().isInterface() : errorString;
+      assert originalName == null || originalName.equals(method.method.name) : errorString;
+      originalName = method.method.name;
+    }
+    return true;
+  }
+
   private static int getMethodStartLine(DexEncodedMethod method) {
     Code code = method.getCode();
     if (code == null) {
@@ -653,7 +693,7 @@
 
     assert !identityMapping
         || inlinedOriginalPosition.get()
-        || checkIdentityMapping(debugInfo, optimizedDebugInfo);
+        || verifyIdentityMapping(debugInfo, optimizedDebugInfo);
 
     dexCode.setDebugInfo(optimizedDebugInfo);
   }
@@ -709,7 +749,7 @@
     dexCode.setDebugInfo(null);
   }
 
-  private static boolean checkIdentityMapping(
+  private static boolean verifyIdentityMapping(
       DexDebugInfo originalDebugInfo, DexDebugInfo optimizedDebugInfo) {
     assert optimizedDebugInfo.startLine == originalDebugInfo.startLine;
     assert optimizedDebugInfo.events.length == originalDebugInfo.events.length;
diff --git a/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java b/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java
index 33f9d7c..40fa54f 100644
--- a/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java
+++ b/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java
@@ -4,13 +4,13 @@
 package com.android.tools.r8.utils;
 
 import com.android.tools.r8.errors.InternalCompilerError;
-import com.android.tools.r8.graph.KeyedDexItem;
+import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.PresortedComparable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
 
-public class OrderedMergingIterator<T extends KeyedDexItem<S>, S extends PresortedComparable<S>>
+public class OrderedMergingIterator<T extends DexEncodedMember<S>, S extends PresortedComparable<S>>
     implements Iterator<T> {
 
   private final List<T> one;
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java
index 78c1b44..5652476 100644
--- a/src/main/java/com/android/tools/r8/utils/Timing.java
+++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -75,6 +75,10 @@
         : Timing.empty();
   }
 
+  public static Timing create(String title, boolean printMemory) {
+    return new Timing(title, printMemory);
+  }
+
   private final Node top;
   private final Stack<Node> stack;
   private final boolean trackMemory;
diff --git a/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
new file mode 100644
index 0000000..294a210
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, 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.utils;
+
+/** Two value continuation value to indicate the continuation of a loop/traversal. */
+public enum TraversalContinuation {
+  CONTINUE,
+  BREAK;
+
+  public final boolean shouldBreak() {
+    return this == BREAK;
+  }
+
+  public final boolean shouldContinue() {
+    return this == CONTINUE;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/JvmTestBuilder.java b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
index 0e510a9..8bc4820 100644
--- a/src/test/java/com/android/tools/r8/JvmTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
@@ -30,6 +30,16 @@
     super(state);
   }
 
+  private Path writeClassesToJar(Collection<Class<?>> classes) {
+    try {
+      Path archive = getState().getNewTempFolder().resolve("out.jar");
+      TestBase.writeClassesToJar(archive, classes);
+      return archive;
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
   public static JvmTestBuilder create(TestState state) {
     return new JvmTestBuilder(state);
   }
@@ -77,14 +87,7 @@
 
   @Override
   public JvmTestBuilder addProgramClasses(Collection<Class<?>> classes) {
-    try {
-      Path out = getState().getNewTempFolder().resolve("out.jar");
-      TestBase.writeClassesToJar(out, classes);
-      addProgramFiles(out);
-      return self();
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    return addProgramFiles(writeClassesToJar(classes));
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
index 2b6cd3c..4a94ac1 100644
--- a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
+++ b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -86,6 +86,30 @@
     return this;
   }
 
+  public KotlinCompilerTool addSourceFilesWithNonKtExtension(TemporaryFolder temp, Path... files) {
+    return addSourceFilesWithNonKtExtension(temp, Arrays.asList(files));
+  }
+
+  public KotlinCompilerTool addSourceFilesWithNonKtExtension(
+      TemporaryFolder temp, Collection<Path> files) {
+    return addSourceFiles(
+        files.stream()
+            .map(
+                fileNotNamedKt -> {
+                  try {
+                    // The Kotlin compiler does not require particular naming of files except for
+                    // the extension,
+                    // so just create a file called source.kt in a new directory.
+                    Path fileNamedKt = temp.newFolder().toPath().resolve("source.kt");
+                    Files.copy(fileNotNamedKt, fileNamedKt);
+                    return fileNamedKt;
+                  } catch (IOException e) {
+                    throw new RuntimeException(e);
+                  }
+                })
+            .collect(Collectors.toList()));
+  }
+
   public KotlinCompilerTool addClasspathFiles(Path... files) {
     return addClasspathFiles(Arrays.asList(files));
   }
diff --git a/src/test/java/com/android/tools/r8/KotlinTestBase.java b/src/test/java/com/android/tools/r8/KotlinTestBase.java
index c3ce381..1a6a428 100644
--- a/src/test/java/com/android/tools/r8/KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/KotlinTestBase.java
@@ -39,6 +39,12 @@
         .collect(Collectors.toList());
   }
 
+  protected static Path getKotlinFileInTestPackage(Package pkg, String fileName)
+      throws IOException {
+    String folder = DescriptorUtils.getBinaryNameFromJavaType(pkg.getName());
+    return getKotlinFileInTest(folder, fileName);
+  }
+
   protected static Path getKotlinFileInTest(String folder, String fileName) {
     return Paths.get(ToolHelper.TESTS_DIR, "java", folder, fileName + FileUtils.KT_EXTENSION);
   }
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 5094ec5..d3bc8da 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -716,6 +716,10 @@
     return dataResources;
   }
 
+  protected static Path getFileInTest(String folder, String fileName) {
+    return Paths.get(ToolHelper.TESTS_DIR, "java", folder, fileName);
+  }
+
   /**
    * Create a temporary JAR file containing all test classes in a package.
    */
@@ -1189,8 +1193,11 @@
     consumer.finished(null);
   }
 
-  protected static void writeClassFileDataToJar(Path output, Collection<byte[]> classes)
-      throws IOException {
+  protected static void writeClassesToJar(Path output, Class<?>... classes) throws IOException {
+    writeClassesToJar(output, Arrays.asList(classes));
+  }
+
+  protected static void writeClassFileDataToJar(Path output, Collection<byte[]> classes) {
     ClassFileConsumer consumer = new ArchiveConsumer(output);
     for (byte[] clazz : classes) {
       consumer.accept(ByteDataView.of(clazz), extractClassDescriptor(clazz), null);
diff --git a/src/test/java/com/android/tools/r8/classlookup/ClasspathClassExtendsProgramClassTest.java b/src/test/java/com/android/tools/r8/classlookup/ClasspathClassExtendsProgramClassTest.java
new file mode 100644
index 0000000..b409e5a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classlookup/ClasspathClassExtendsProgramClassTest.java
@@ -0,0 +1,105 @@
+// Copyright (c) 2020, 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.classlookup;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.references.Reference;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+// This test runs an R8 setup where a classpath class extends a program class and the program in
+// turn uses the classpath class. Having such a cyclic compilation setup is very odd, but with
+// sufficient keep rules it can work.
+@RunWith(Parameterized.class)
+public class ClasspathClassExtendsProgramClassTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public ClasspathClassExtendsProgramClassTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  public static class ProgramClass {
+
+    public void foo() {
+      System.out.println("ProgramClass::foo");
+    }
+  }
+
+  static class Main {
+    public static void main(String[] args) {
+      ProgramClass object = args.length == 42 ? new ProgramClass() : new ClasspathClass();
+      object.foo();
+    }
+  }
+
+  public static class ClasspathIndirection extends ProgramClass {
+    // Intentionally empty.
+  }
+
+  public static class ClasspathClass extends ClasspathIndirection {
+
+    @Override
+    public void foo() {
+      System.out.println("ClasspathClass::foo");
+    }
+  }
+
+  @Test
+  public void testReference() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class, ProgramClass.class)
+        .addRunClasspathFiles(compileClasspath())
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("ClasspathClass::foo");
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .setMinApi(parameters.getApiLevel())
+        .addProgramClasses(Main.class, ProgramClass.class)
+        .addClasspathClasses(ClasspathClass.class, ClasspathIndirection.class)
+        .addKeepMainRule(Main.class)
+        // Keep the method that is overridden by the classpath class.
+        .addKeepMethodRules(Reference.methodFromMethod(ProgramClass.class.getDeclaredMethod("foo")))
+        .addRunClasspathFiles(compileClasspath())
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("ClasspathClass::foo");
+  }
+
+  private Path compileClasspath() throws java.io.IOException, CompilationFailedException {
+    return compile(
+        ImmutableList.of(ClasspathClass.class, ClasspathIndirection.class),
+        ImmutableList.of(ProgramClass.class));
+  }
+
+  private Path compile(Collection<Class<?>> compilationUnit, Collection<Class<?>> classpath)
+      throws java.io.IOException, CompilationFailedException {
+    if (parameters.isCfRuntime()) {
+      Path out = temp.newFolder().toPath().resolve("out.jar");
+      writeClassesToJar(out, compilationUnit);
+      return out;
+    }
+    return testForD8()
+        .setMinApi(parameters.getApiLevel())
+        .addProgramClasses(compilationUnit)
+        .addClasspathClasses(classpath)
+        .compile()
+        .writeToZip();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java b/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java
index 83682b2..8096c47 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java
@@ -8,11 +8,13 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -23,7 +25,7 @@
 import java.util.stream.Collectors;
 import org.junit.Test;
 
-public class TestBackportedNotPresentInAndroidJar {
+public class TestBackportedNotPresentInAndroidJar extends TestBase {
 
   @Test
   public void testBackportedMethodsPerAPILevel() throws Exception {
@@ -40,7 +42,7 @@
       options.minApiLevel = apiLevel.getLevel();
       List<DexMethod> backportedMethods =
           BackportedMethodRewriter.generateListOfBackportedMethods(
-              null, options, ThreadUtils.getExecutorService(options));
+              AndroidApp.builder().build(), options, ThreadUtils.getExecutorService(options));
       for (DexMethod method : backportedMethods) {
         // Two different DexItemFactories are in play, but as toSourceString is used for lookup
         // that is not an issue.
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index 53bb117..666cb87 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -17,6 +17,7 @@
 import com.android.tools.r8.code.IfNez;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.code.ReturnVoid;
+import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexCode.Try;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -160,7 +161,8 @@
         null);
     MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false);
     DexEncodedMethod method =
-        new DexEncodedMethod(null, flags, null, ParameterAnnotationsList.empty(), code);
+        new DexEncodedMethod(
+            null, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), code);
     return new JumboStringRewriter(method, string, factory).rewrite();
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
index 0924546..4484311 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
@@ -7,36 +7,39 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
-import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import org.junit.Before;
 import org.junit.Test;
 
-public class R8GMSCoreLookupTest {
+public class R8GMSCoreLookupTest extends TestBase {
 
   static final String APP_DIR = "third_party/gmscore/v5/";
   private AndroidApp app;
   private DirectMappedDexApplication program;
   private AppInfoWithSubtyping appInfo;
+  private AppView<?> appView;
 
   @Before
-  public void readGMSCore() throws IOException, ExecutionException {
+  public void readGMSCore() throws Exception {
     Path directory = Paths.get(APP_DIR);
     app = ToolHelper.builderFromProgramDirectory(directory).build();
     Path mapFile = directory.resolve(ToolHelper.DEFAULT_PROGUARD_MAP_FILE);
@@ -51,6 +54,7 @@
             .read(proguardMap, executorService)
             .toDirect();
     appInfo = new AppInfoWithSubtyping(program);
+    appView = computeAppViewWithSubtyping(app);
   }
 
   private void testVirtualLookup(DexProgramClass clazz, DexEncodedMethod method) {
@@ -59,16 +63,20 @@
     assertEquals(appInfo.resolveMethod(id.holder, method.method).getSingleTarget(), method);
 
     // Check lookup targets with include method.
-    Set<DexEncodedMethod> targets =
-        appInfo.resolveMethodOnClass(clazz, method.method).lookupVirtualDispatchTargets(appInfo);
+    ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(clazz, method.method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView, appInfo);
+    assertTrue(lookupResult.isLookupResultSuccess());
+    Set<DexEncodedMethod> targets = lookupResult.asLookupResultSuccess().getMethodTargets();
     assertTrue(targets.contains(method));
   }
 
   private void testInterfaceLookup(DexProgramClass clazz, DexEncodedMethod method) {
-    Set<DexEncodedMethod> targets =
+    LookupResult lookupResult =
         appInfo
             .resolveMethodOnInterface(clazz, method.method)
-            .lookupVirtualDispatchTargets(appInfo);
+            .lookupVirtualDispatchTargets(appView, appInfo);
+    assertTrue(lookupResult.isLookupResultSuccess());
+    Set<DexEncodedMethod> targets = lookupResult.asLookupResultSuccess().getMethodTargets();
     if (appInfo.subtypes(method.method.holder).stream()
         .allMatch(t -> appInfo.definitionFor(t).isInterface())) {
       assertEquals(
@@ -81,8 +89,6 @@
     }
   }
 
-
-
   private void testLookup(DexProgramClass clazz) {
     if (clazz.isInterface()) {
       for (DexEncodedMethod method : clazz.virtualMethods()) {
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
index b567014..7b7036f 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.ir.conversion;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
@@ -20,7 +21,8 @@
             dexItemFactory.createProto(dexItemFactory.voidType),
             methodName);
     return new Node(
-        new DexEncodedMethod(signature, null, null, ParameterAnnotationsList.empty(), null));
+        new DexEncodedMethod(
+            signature, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null));
   }
 
   Node createForceInlinedNode(String methodName) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentForwardingConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentForwardingConstructorTest.java
new file mode 100644
index 0000000..a118c85
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentForwardingConstructorTest.java
@@ -0,0 +1,107 @@
+// Copyright (c) 2020, 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentForwardingConstructorTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public FieldInitializedByConstantArgumentForwardingConstructorTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(FieldInitializedByConstantArgumentForwardingConstructorTest.class)
+        .addKeepMainRule(TestClass.class)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("Live!", "Live!");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+    assertThat(testClassSubject, isPresent());
+    assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+    // TODO(b/147652121): Should be absent.
+    assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      if (allocationSite1().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+
+      if (allocationSite2().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+    }
+
+    @NeverInline
+    static A allocationSite1() {
+      return new A();
+    }
+
+    @NeverInline
+    static A allocationSite2() {
+      return new A(42);
+    }
+
+    @NeverInline
+    static void live() {
+      System.out.println("Live!");
+    }
+
+    @NeverInline
+    static void dead() {
+      System.out.println("Dead!");
+    }
+  }
+
+  @NeverClassInline
+  static class A {
+
+    int x;
+
+    A() {
+      this(42);
+    }
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentMultipleConstructorsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentMultipleConstructorsTest.java
new file mode 100644
index 0000000..6663b91
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentMultipleConstructorsTest.java
@@ -0,0 +1,107 @@
+// Copyright (c) 2020, 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentMultipleConstructorsTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public FieldInitializedByConstantArgumentMultipleConstructorsTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(FieldInitializedByConstantArgumentMultipleConstructorsTest.class)
+        .addKeepMainRule(TestClass.class)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("Live!", "Live!");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+    assertThat(testClassSubject, isPresent());
+    assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+    // TODO(b/147652121): Should be absent.
+    assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      if (allocationSite1().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+
+      if (allocationSite2().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+    }
+
+    @NeverInline
+    static A allocationSite1() {
+      return new A(42);
+    }
+
+    @NeverInline
+    static A allocationSite2() {
+      return new A(42, null);
+    }
+
+    @NeverInline
+    static void live() {
+      System.out.println("Live!");
+    }
+
+    @NeverInline
+    static void dead() {
+      System.out.println("Dead!");
+    }
+  }
+
+  @NeverClassInline
+  static class A {
+
+    int x;
+
+    A(int x) {
+      this.x = x;
+    }
+
+    A(int x, Object unused) {
+      this.x = x;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentSubtypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentSubtypeTest.java
new file mode 100644
index 0000000..c460e16
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentSubtypeTest.java
@@ -0,0 +1,111 @@
+// Copyright (c) 2020, 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentSubtypeTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public FieldInitializedByConstantArgumentSubtypeTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(FieldInitializedByConstantArgumentSubtypeTest.class)
+        .addKeepMainRule(TestClass.class)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("Live!", "Live!");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+    assertThat(testClassSubject, isPresent());
+    assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+    // TODO(b/147652121): Should be absent.
+    assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      if (allocationSite1().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+
+      if (allocationSite2().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+    }
+
+    @NeverInline
+    static A allocationSite1() {
+      return new A(42);
+    }
+
+    @NeverInline
+    static A allocationSite2() {
+      return new B(42);
+    }
+
+    @NeverInline
+    static void live() {
+      System.out.println("Live!");
+    }
+
+    @NeverInline
+    static void dead() {
+      System.out.println("Dead!");
+    }
+  }
+
+  @NeverClassInline
+  static class A {
+
+    int x;
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+
+  @NeverClassInline
+  static class B extends A {
+
+    B(int x) {
+      super(x);
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentTest.java
new file mode 100644
index 0000000..beecf65
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentTest.java
@@ -0,0 +1,103 @@
+// Copyright (c) 2020, 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public FieldInitializedByConstantArgumentTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(FieldInitializedByConstantArgumentTest.class)
+        .addKeepMainRule(TestClass.class)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("Live!", "Live!");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+    assertThat(testClassSubject, isPresent());
+    assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+    // TODO(b/147652121): Should be absent.
+    assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      if (allocationSite1().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+
+      if (allocationSite2().x == 42) {
+        live();
+      } else {
+        dead();
+      }
+    }
+
+    @NeverInline
+    static A allocationSite1() {
+      return new A(42);
+    }
+
+    @NeverInline
+    static A allocationSite2() {
+      return new A(42);
+    }
+
+    @NeverInline
+    static void live() {
+      System.out.println("Live!");
+    }
+
+    @NeverInline
+    static void dead() {
+      System.out.println("Dead!");
+    }
+  }
+
+  @NeverClassInline
+  static class A {
+
+    int x;
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantInOneConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantInOneConstructorTest.java
new file mode 100644
index 0000000..71ef038
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantInOneConstructorTest.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2020, 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantInOneConstructorTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public FieldInitializedByConstantInOneConstructorTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(FieldInitializedByConstantInOneConstructorTest.class)
+        .addKeepMainRule(TestClass.class)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("Live!", "true");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+    assertThat(testClassSubject, isPresent());
+    assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+    // TODO(b/147652121): Should be absent.
+    assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      A obj1 = new A();
+      if (obj1.x == 42) {
+        live();
+      } else {
+        dead();
+      }
+
+      A obj2 = new A((int) System.currentTimeMillis());
+      System.out.println(obj2.x != 42);
+    }
+
+    @NeverInline
+    static void live() {
+      System.out.println("Live!");
+    }
+
+    @NeverInline
+    static void dead() {
+      System.out.println("Dead!");
+    }
+  }
+
+  @NeverClassInline
+  static class A {
+
+    int x;
+
+    A() {
+      this.x = 42;
+    }
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByNonConstantArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByNonConstantArgumentTest.java
new file mode 100644
index 0000000..c0c12e2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByNonConstantArgumentTest.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2020, 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByNonConstantArgumentTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public FieldInitializedByNonConstantArgumentTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(FieldInitializedByNonConstantArgumentTest.class)
+        .addKeepMainRule(TestClass.class)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("Live!", "Live!");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+    assertThat(testClassSubject, isPresent());
+    assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+    // TODO(b/147652121): Should be absent.
+    assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      A obj1 = new A(42);
+      if (obj1.x == 42) {
+        live();
+      } else {
+        dead();
+      }
+
+      A obj2 = new A(43);
+      if (obj2.x == 43) {
+        live();
+      } else {
+        dead();
+      }
+    }
+
+    @NeverInline
+    static void live() {
+      System.out.println("Live!");
+    }
+
+    @NeverInline
+    static void dead() {
+      System.out.println("Dead!");
+    }
+  }
+
+  @NeverClassInline
+  static class A {
+
+    int x;
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/B148525512.java b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/B148525512.java
new file mode 100644
index 0000000..a06dcf8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/B148525512.java
@@ -0,0 +1,155 @@
+// Copyright (c) 2020, 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.kotlin.lambda.b148525512;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer;
+import com.android.tools.r8.KotlinTestBase;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.utils.ArchiveResourceProvider;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class B148525512 extends KotlinTestBase {
+
+  private static final Package pkg = B148525512.class.getPackage();
+  private static final String kotlinTestClassesPackage = pkg.getName();
+  private static final String baseKtClassName = kotlinTestClassesPackage + ".BaseKt";
+  private static final String featureKtClassNamet = kotlinTestClassesPackage + ".FeatureKt";
+  private static final String baseClassName = kotlinTestClassesPackage + ".Base";
+
+  private static final Map<KotlinTargetVersion, Path> kotlinBaseClasses = new HashMap<>();
+  private static final Map<KotlinTargetVersion, Path> kotlinFeatureClasses = new HashMap<>();
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0},{1}")
+  public static Collection<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withDexRuntimes().withAllApiLevels().build(),
+        KotlinTargetVersion.values());
+  }
+
+  public B148525512(TestParameters parameters, KotlinTargetVersion targetVersion) {
+    super(targetVersion);
+    this.parameters = parameters;
+  }
+
+  @ClassRule public static TemporaryFolder classTemp = new TemporaryFolder();
+
+  @BeforeClass
+  public static void compileKotlin() throws Exception {
+    // Compile the base Kotlin with the FeatureAPI Java class on classpath.
+    Path featureApiJar = classTemp.newFile("feature_api.jar").toPath();
+    writeClassesToJar(featureApiJar, FeatureAPI.class);
+    for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
+      Path ktBaseClasses =
+          kotlinc(KOTLINC, targetVersion)
+              .addClasspathFiles(featureApiJar)
+              .addSourceFiles(getKotlinFileInTestPackage(pkg, "base"))
+              .compile();
+      kotlinBaseClasses.put(targetVersion, ktBaseClasses);
+      // Compile the feature Kotlin code with the base classes on classpath.
+      Path ktFeatureClasses =
+          kotlinc(KOTLINC, targetVersion)
+              .addClasspathFiles(ktBaseClasses)
+              .addSourceFiles(getKotlinFileInTestPackage(pkg, "feature"))
+              .compile();
+      kotlinFeatureClasses.put(targetVersion, ktFeatureClasses);
+    }
+  }
+
+  private void checkLambdaGroups(CodeInspector inspector) {
+    List<FoundClassSubject> lambdaGroups =
+        inspector.allClasses().stream()
+            .filter(clazz -> clazz.getOriginalName().contains("LambdaGroup"))
+            .collect(Collectors.toList());
+    assertEquals(1, lambdaGroups.size());
+    MethodSubject invokeMethod = lambdaGroups.get(0).uniqueMethodWithName("invoke");
+    assertThat(invokeMethod, isPresent());
+    // The lambda group has 2 captures which capture "Base".
+    assertEquals(
+        2,
+        invokeMethod
+            .streamInstructions()
+            .filter(InstructionSubject::isCheckCast)
+            .filter(
+                instruction ->
+                    instruction.asCheckCast().getType().toSourceString().contains("Base"))
+            .count());
+    // The lambda group has no captures which capture "Feature" (lambdas in the feature are not
+    // in this lambda group).
+    assertTrue(
+        invokeMethod
+            .streamInstructions()
+            .filter(InstructionSubject::isCheckCast)
+            .noneMatch(
+                instruction ->
+                    instruction.asCheckCast().getType().toSourceString().contains("Feature")));
+  }
+
+  @Test
+  public void test() throws Exception {
+    Path featureCode = temp.newFile("feature.zip").toPath();
+    R8TestCompileResult compileResult =
+        testForR8(parameters.getBackend())
+            .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+            .addProgramFiles(kotlinBaseClasses.get(targetVersion))
+            .addProgramClasses(FeatureAPI.class)
+            .addKeepMainRule(baseKtClassName)
+            .addKeepClassAndMembersRules(baseClassName)
+            .addKeepClassAndMembersRules(featureKtClassNamet)
+            .addKeepClassAndMembersRules(FeatureAPI.class)
+            .setMinApi(parameters.getApiLevel())
+            .noMinification() // The check cast inspection above relies on original names.
+            .addFeatureSplit(
+                builder ->
+                    builder
+                        .addProgramResourceProvider(
+                            ArchiveResourceProvider.fromArchive(
+                                kotlinFeatureClasses.get(targetVersion), true))
+                        .setProgramConsumer(new ArchiveConsumer(featureCode, false))
+                        .build())
+            .allowDiagnosticWarningMessages()
+            .compile()
+            .assertAllWarningMessagesMatch(
+                equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
+            .inspect(this::checkLambdaGroups);
+
+    // Run the code without the feature code present.
+    compileResult
+        .run(parameters.getRuntime(), baseKtClassName)
+        .assertSuccessWithOutputLines("1", "2");
+
+    // Run the code with the feature code present.
+    compileResult
+        .addRunClasspathFiles(featureCode)
+        .run(parameters.getRuntime(), baseKtClassName)
+        .assertSuccessWithOutputLines("1", "2", "3", "4");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/FeatureAPI.java b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/FeatureAPI.java
new file mode 100644
index 0000000..95bc790
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/FeatureAPI.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, 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.kotlin.lambda.b148525512;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class FeatureAPI {
+  public static boolean hasFeature() {
+    try {
+      Class.forName(FeatureAPI.class.getPackage().getName() + ".FeatureKt");
+    } catch (ClassNotFoundException e) {
+      return false;
+    }
+    return true;
+  }
+
+  public static void feature(int i)
+      throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
+          IllegalAccessException {
+    Class<?> featureKtClass = Class.forName(FeatureAPI.class.getPackage().getName() + ".FeatureKt");
+    Method featureMethod = featureKtClass.getMethod("feature", int.class);
+    featureMethod.invoke(null, i);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/base.kt b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/base.kt
new file mode 100644
index 0000000..aced216
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/base.kt
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, 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.kotlin.lambda.b148525512
+
+fun printInt(l: () -> Int ) = println(l())
+
+open class Base(@JvmField var x: Int, @JvmField var y: Int)
+
+fun main(args: Array<String>) {
+  val base = Base(args.size + 1, args.size + 2)
+  printInt { base.x }
+  printInt { base.y }
+  if (FeatureAPI.hasFeature()) {
+    FeatureAPI.feature(args.size + 3)
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/feature.kt b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/feature.kt
new file mode 100644
index 0000000..3480225
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/feature.kt
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, 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.kotlin.lambda.b148525512
+
+class Feature(x: Int, y: Int) : Base(x, y)
+
+fun feature(i: Int) {
+  val f = Feature(i, i + 1)
+  printInt { f.x }
+  printInt { f.y }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
index 16385b4..f77cdb9 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
@@ -94,6 +94,8 @@
             .addProgramFiles(companionLibJarMap.get(targetVersion))
             // Keep the B class and its interface (which has the doStuff method).
             .addKeepRules("-keep class **.B")
+            // Property in companion with @JvmField is defined in the host class, without accessors.
+            .addKeepRules("-keepclassmembers class **.B { *** elt2; }")
             .addKeepRules("-keep class **.I { <methods>; }")
             // Keep getters for B$Companion.(eltN|foo) which will be referenced at the app.
             .addKeepRules("-keepclassmembers class **.B$* { *** get*(...); }")
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
index ec9cdc7..54675ca 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
@@ -10,7 +10,9 @@
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
@@ -21,10 +23,12 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
 import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
+import com.android.tools.r8.utils.codeinspector.KmValueParameterSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.nio.file.Path;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -91,7 +95,7 @@
     assertThat(
         kotlinTestCompileResult.stderr, containsString("but java.util.Map<K, V> was expected"));
     assertThat(
-        kotlinTestCompileResult.stderr, containsString("no value passed for parameter 'p2'"));
+        kotlinTestCompileResult.stderr, not(containsString("no value passed for parameter 'p2'")));
   }
 
   private void inspect(CodeInspector inspector) {
@@ -114,7 +118,11 @@
 
     KmFunctionSubject kmFunction = kmPackage.kmFunctionExtensionWithUniqueName("applyMap");
     assertThat(kmFunction, isExtensionFunction());
-    // TODO(b/70169921): inspect 2nd arg has flag that says it has a default value.
-    //  https://github.com/JetBrains/kotlin/blob/master/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt#L455
+    List<KmValueParameterSubject> valueParameters = kmFunction.valueParameters();
+    assertEquals(2, valueParameters.size());
+    // TODO(b/70169921): inspect 1st arg is Map with correct type parameter.
+    KmValueParameterSubject valueParameter = valueParameters.get(1);
+    assertTrue(valueParameter.declaresDefaultValue());
+    assertEquals("Lkotlin/String;", valueParameter.type().descriptor());
   }
 }
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
index f4e79f3..1bf7552 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
@@ -10,7 +10,9 @@
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
@@ -20,10 +22,12 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
 import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
+import com.android.tools.r8.utils.codeinspector.KmValueParameterSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.nio.file.Path;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -66,7 +70,7 @@
     Path libJar =
         testForR8(parameters.getBackend())
             .addProgramFiles(varargLibJarMap.get(targetVersion))
-            // keep SomClass#foo, since there is a method reference in the app.
+            // keep SomeClass#foo, since there is a method reference in the app.
             .addKeepRules("-keep class **.SomeClass { *** foo(...); }")
             // Keep LibKt, along with bar function.
             .addKeepRules("-keep class **.LibKt { *** bar(...); }")
@@ -87,7 +91,8 @@
     assertNotEquals(0, kotlinTestCompileResult.exitCode);
     assertThat(
         kotlinTestCompileResult.stderr,
-        containsString("type mismatch: inferred type is String but Array<T> was expected"));
+        not(containsString("type mismatch: inferred type is String but Array<T> was expected")));
+    assertThat(kotlinTestCompileResult.stderr, containsString("unresolved reference: foo"));
   }
 
   private void inspect(CodeInspector inspector) {
@@ -115,6 +120,11 @@
 
     KmFunctionSubject kmFunction = kmPackage.kmFunctionWithUniqueName("bar");
     assertThat(kmFunction, not(isExtensionFunction()));
-    // TODO(b/70169921): inspect 1st arg is `vararg`.
+    List<KmValueParameterSubject> valueParameters = kmFunction.valueParameters();
+    assertEquals(2, valueParameters.size());
+    KmValueParameterSubject valueParameter = valueParameters.get(0);
+    assertTrue(valueParameter.isVararg());
+    assertEquals("Lkotlin/String;", valueParameter.varargElementType().descriptor());
+    // TODO(b/70169921): inspect 2nd arg is lambda with correct type parameter.
   }
 }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
index d8b230d..34abe12 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
@@ -9,6 +9,8 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
@@ -18,8 +20,10 @@
 import com.android.tools.r8.shaking.ProguardKeepAttributes;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FieldSubject;
 import com.android.tools.r8.utils.codeinspector.KmClassSubject;
 import com.android.tools.r8.utils.codeinspector.KmPropertySubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.nio.file.Path;
 import java.util.Collection;
 import java.util.HashMap;
@@ -85,7 +89,7 @@
         .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
         .addClasspath(output)
         .run(parameters.getRuntime(), PKG + ".fragile_property_only_getter.Getter_userKt")
-        .assertSuccessWithOutputLines("true", "false", "Hey");
+        .assertSuccessWithOutputLines("true", "false", "Hey Jude");
   }
 
   private void inspectGetterOnly(CodeInspector inspector) {
@@ -94,6 +98,14 @@
     assertThat(person, isPresent());
     assertThat(person, not(isRenamed()));
 
+    FieldSubject backingField = person.uniqueFieldWithName("name");
+    assertThat(backingField, isRenamed());
+    MethodSubject getterForName = person.uniqueMethodWithName("getName");
+    assertThat(getterForName, isPresent());
+    assertThat(getterForName, not(isRenamed()));
+    MethodSubject setterForName = person.uniqueMethodWithName("setName");
+    assertThat(setterForName, not(isPresent()));
+
     // API entry is kept, hence the presence of Metadata.
     KmClassSubject kmClass = person.getKmClass();
     assertThat(kmClass, isPresent());
@@ -101,8 +113,12 @@
     KmPropertySubject name = kmClass.kmPropertyWithUniqueName("name");
     assertThat(name, isPresent());
     assertThat(name, not(isExtensionProperty()));
+    // Property name is not renamed, due to the kept getter.
+    assertEquals("name", name.name());
     assertNotNull(name.fieldSignature());
+    assertEquals(backingField.getJvmFieldSignatureAsString(), name.fieldSignature().asString());
     assertNotNull(name.getterSignature());
+    assertEquals(getterForName.getJvmMethodSignatureAsString(), name.getterSignature().asString());
     assertNull(name.setterSignature());
 
     KmPropertySubject familyName = kmClass.kmPropertyWithUniqueName("familyName");
@@ -159,6 +175,7 @@
     ClassSubject person = inspector.clazz(personClassName);
     assertThat(person, isPresent());
     assertThat(person, not(isRenamed()));
+
     // API entry is kept, hence the presence of Metadata.
     KmClassSubject kmClass = person.getKmClass();
     assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
index b643c4b..57cd84c 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
@@ -148,7 +148,8 @@
     ProcessResult kotlinTestCompileResult =
         kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
             .addClasspathFiles(libJar)
-            .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/sealed_app", "invalid"))
+            .addSourceFilesWithNonKtExtension(
+                temp, getFileInTest(PKG_PREFIX + "/sealed_app", "invalid.kt_txt"))
             .setOutputPath(temp.newFolder().toPath())
             .compileRaw();
 
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt
index b85bd2e..b3aba2e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt
@@ -11,5 +11,5 @@
 
   println(x.canDrink)
   println(x.married)
-  println(y.firstName)
+  println(y.name)
 }
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt_txt
similarity index 100%
rename from src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt
rename to src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt_txt
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 3f8c11f..03ab057 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -830,7 +830,7 @@
                 DexAnnotationSet.empty(),
                 ParameterAnnotationsList.empty(),
                 code);
-        AppView<?> appView = AppView.createForR8(null, options);
+        AppView<?> appView = AppView.createForR8(appInfo, options);
         IRCode ir = code.buildIR(method, appView, Origin.unknown());
         RegisterAllocator allocator = new LinearScanRegisterAllocator(appView, ir);
         method.setCode(ir, allocator, appView);
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java
index 0e5e1c6..26873f4 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java
@@ -63,7 +63,7 @@
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().build();
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
   }
 
   public ApplyMappingLibraryMemberRenamingTests(TestParameters parameters) {
@@ -78,7 +78,7 @@
             .addProgramClasses(Dto.class, Interface.class, Main.class)
             .addKeepClassAndMembersRules(Main.class)
             .addKeepClassAndMembersRulesWithAllowObfuscation(Interface.class, Dto.class)
-            .setMinApi(parameters.getRuntime())
+            .setMinApi(parameters.getApiLevel())
             .compile()
             .inspect(
                 codeInspector -> {
@@ -93,7 +93,7 @@
         .addClasspathClasses(Dto.class, Interface.class, Main.class)
         .addKeepAllClassesRule()
         .addApplyMapping(libraryCompileResult.getProguardMap())
-        .setMinApi(parameters.getRuntime())
+        .setMinApi(parameters.getApiLevel())
         .compile()
         .addRunClasspathFiles(libraryCompileResult.writeToZip())
         .run(parameters.getRuntime(), ClientTest.class)
diff --git a/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
index 8034ad7..079a8f5 100644
--- a/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
@@ -44,7 +44,7 @@
         factory.createType(DescriptorUtils.javaTypeToDescriptor(Foo.class.getTypeName()));
     DexType[] arrayTypes =
         new DexType[] {
-          factory.createType("[I"),
+          factory.intArrayType,
           factory.stringArrayType,
           factory.objectArrayType,
           factory.createArrayType(2, fooType)
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 45a9a20..ba27c33 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -7,9 +7,11 @@
 
 import com.android.tools.r8.AsmTestBase;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.resolution.singletarget.Main;
 import com.android.tools.r8.resolution.singletarget.one.AbstractSubClass;
@@ -43,9 +45,9 @@
 @RunWith(Parameterized.class)
 public class SingleTargetLookupTest extends AsmTestBase {
 
-  /**
-   * Initialized in @Before rule.
-   */
+  /** Initialized in @Before rule. */
+  public static AppView<AppInfoWithLiveness> appView;
+
   public static AppInfoWithLiveness appInfo;
 
   public static List<Class<?>> CLASSES =
@@ -83,9 +85,8 @@
 
   @BeforeClass
   public static void computeAppInfo() throws Exception {
-    appInfo =
-        computeAppViewWithLiveness(readClassesAndAsmDump(CLASSES, ASM_CLASSES), Main.class)
-            .appInfo();
+    appView = computeAppViewWithLiveness(readClassesAndAsmDump(CLASSES, ASM_CLASSES), Main.class);
+    appInfo = appView.appInfo();
   }
 
   private static Object[] singleTarget(String name, Class<?> receiverAndTarget) {
@@ -222,7 +223,9 @@
         appInfo.resolveMethod(toType(invokeReceiver, appInfo), method).getSingleTarget());
     ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
     if (resolutionResult.isVirtualTarget()) {
-      Set<DexEncodedMethod> targets = resolutionResult.lookupVirtualDispatchTargets(appInfo);
+      LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView, appInfo);
+      assertTrue(lookupResult.isLookupResultSuccess());
+      Set<DexEncodedMethod> targets = lookupResult.asLookupResultSuccess().getMethodTargets();
       Set<DexType> targetHolders =
           targets.stream().map(m -> m.method.holder).collect(Collectors.toSet());
       Assert.assertEquals(allTargetHolders.size(), targetHolders.size());
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java
index b119874..3fcc33d 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -48,18 +51,23 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "bar", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
-        ImmutableSet.of(A.class.getTypeName() + ".bar", J.class.getTypeName() + ".bar");
+        ImmutableSet.of(
+            I.class.getTypeName() + ".bar",
+            A.class.getTypeName() + ".bar",
+            J.class.getTypeName() + ".bar");
     assertEquals(expected, targets);
   }
 
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java
index f926d4b..bdd5dd3 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -47,13 +50,15 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
-        computeAppViewWithLiveness(buildClasses(I.class, A.class, Main.class).build(), Main.class)
-            .appInfo();
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(buildClasses(I.class, A.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "bar", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
index 61e872e..266cb48 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
@@ -6,6 +6,7 @@
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -15,8 +16,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -47,16 +51,19 @@
   @Test
   public void testDynamicLookupTargets() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, Main.class)
-                    .addClassProgramData(setAImplementsIAndJ())
-                    .build(),
-                Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, Main.class)
+                .addClassProgramData(setAImplementsIAndJ())
+                .build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
@@ -84,18 +91,21 @@
   }
 
   @Test
-  public void testtestDynamicLookupTargetsWithIndirectDefault() throws Exception {
+  public void testDynamicLookupTargetsWithIndirectDefault() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, K.class, Main.class)
-                    .addClassProgramData(setAimplementsIandK())
-                    .build(),
-                Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, K.class, Main.class)
+                .addClassProgramData(setAimplementsIandK())
+                .build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
index a69a18b..2614319 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.TestRuntime.DexRuntime;
 import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.transformers.ClassTransformer;
@@ -49,19 +50,17 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(A.class, B.class)
-                    .addClassProgramData(transformI(), transformMain())
-                    .build(),
-                Main.class)
-            .appInfo();
+            buildClasses(A.class, B.class)
+                .addClassProgramData(transformI(), transformMain())
+                .build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "<clinit>", appInfo.dexItemFactory());
     Assert.assertThrows(
         AssertionError.class,
-        () -> {
-          appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo);
-        });
+        () -> appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appView));
   }
 
   private Matcher<String> getExpected() {
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
index 3b6022b..1ca966b 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.AndroidApiLevel;
@@ -42,15 +43,15 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.getRuntime().equals(TestRuntime.getDefaultJavaRuntime()));
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(A.class, I.class).addClassProgramData(transformMain()).build(),
-                Main.class)
-            .appInfo();
+            buildClasses(A.class, I.class).addClassProgramData(transformMain()).build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "bar", appInfo.dexItemFactory());
     Assert.assertThrows(
         AssertionError.class,
-        () -> appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo));
+        () -> appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appView));
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java
index 88fd988..251fa37 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -47,14 +50,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(J.class, "bar", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java
index 23c2215..eff0088 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -47,14 +50,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java
index 03a6141..9552212 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -48,14 +51,16 @@
   public void testResolution() throws Exception {
     // The resolution is runtime independent, so just run it on the default CF VM.
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java
index e73a10e..41d4879 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -13,8 +14,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -46,15 +49,17 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, A.class, B.class, C.class, Main.class).build(),
-                Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, A.class, B.class, C.class, Main.class).build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java
index 24916b0..84236e5 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -13,8 +14,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -46,14 +49,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java
index a9b34f2..a952bb3 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.interfacetargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -13,8 +14,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -46,14 +49,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
new file mode 100644
index 0000000..f465727
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
@@ -0,0 +1,114 @@
+// Copyright (c) 2020, 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.resolution.packageprivate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.a.A;
+import com.android.tools.r8.resolution.packageprivate.a.A.B;
+import com.android.tools.r8.resolution.packageprivate.a.D;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PackagePrivateReentryTest extends TestBase {
+
+  private final TestParameters parameters;
+  private static final String[] EXPECTED = new String[] {"D.foo", "D.bar", "D.foo", "D.bar"};
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public PackagePrivateReentryTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void testResolution() throws Exception {
+    assumeTrue(parameters.useRuntimeAsNoneRuntime());
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(
+            buildClasses(A.class, B.class, C.class, D.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
+    DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
+    Set<String> targets =
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+            .map(DexEncodedMethod::qualifiedName)
+            .collect(Collectors.toSet());
+    // TODO(b/149363086): Fix expection, should not include C.bar().
+    ImmutableSet<String> expected =
+        ImmutableSet.of(
+            A.class.getTypeName() + ".bar",
+            B.class.getTypeName() + ".bar",
+            C.class.getTypeName() + ".bar",
+            D.class.getTypeName() + ".bar");
+    assertEquals(expected, targets);
+  }
+
+  @Test
+  public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+    TestRunResult<?> runResult =
+        testForRuntime(parameters)
+            .addProgramClasses(A.class, B.class, C.class, D.class, Main.class)
+            .run(parameters.getRuntime(), Main.class)
+            .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(A.class, B.class, C.class, D.class, Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  public static class C extends B {
+    @Override
+    public void foo() {
+      System.out.println("C.foo");
+    }
+
+    public void bar() {
+      System.out.println("C.bar");
+    }
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      D d = new D();
+      A.run(d);
+      d.foo();
+      d.bar();
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
new file mode 100644
index 0000000..35791e7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
@@ -0,0 +1,123 @@
+// Copyright (c) 2020, 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.resolution.packageprivate;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.PackagePrivateReentryTest.C;
+import com.android.tools.r8.resolution.packageprivate.a.A;
+import com.android.tools.r8.resolution.packageprivate.a.A.B;
+import com.android.tools.r8.resolution.packageprivate.a.D;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PackagePrivateReentryWithNarrowingTest extends TestBase {
+
+  private final TestParameters parameters;
+  private static final String[] EXPECTED = new String[] {"D.foo", "D.bar", "D.foo", "D.bar"};
+  private static final String[] EXPECTED_ART = new String[] {"D.foo", "D.bar", "D.foo", "C.bar"};
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public PackagePrivateReentryWithNarrowingTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void testResolution() throws Exception {
+    assumeTrue(parameters.useRuntimeAsNoneRuntime());
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(
+            buildClasses(A.class, B.class, C.class, D.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
+    DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
+    Set<String> targets =
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+            .map(DexEncodedMethod::qualifiedName)
+            .collect(Collectors.toSet());
+    // TODO(b/149363086): Fix expection, should not include C.bar().
+    ImmutableSet<String> expected =
+        ImmutableSet.of(
+            A.class.getTypeName() + ".bar",
+            B.class.getTypeName() + ".bar",
+            C.class.getTypeName() + ".bar",
+            D.class.getTypeName() + ".bar");
+    assertEquals(expected, targets);
+  }
+
+  @Test
+  public void testRuntime()
+      throws ExecutionException, CompilationFailedException, IOException, NoSuchMethodException {
+    TestRunResult<?> runResult =
+        testForRuntime(parameters)
+            .addProgramClasses(A.class, B.class, C.class, Main.class)
+            .addProgramClassFileData(getDWithPackagePrivateFoo())
+            .run(parameters.getRuntime(), Main.class);
+    if (parameters.isCfRuntime()
+        || parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+      runResult.assertSuccessWithOutputLines(EXPECTED);
+    } else {
+      runResult.assertSuccessWithOutputLines(EXPECTED_ART);
+    }
+  }
+
+  @Test
+  public void testR8()
+      throws ExecutionException, CompilationFailedException, IOException, NoSuchMethodException {
+    // TODO(b/149363086): Fix test.
+    testForR8(parameters.getBackend())
+        .addProgramClasses(A.class, B.class, C.class, Main.class)
+        .addProgramClassFileData(getDWithPackagePrivateFoo())
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertFailureWithErrorThatMatches(containsString("IllegalAccessError"));
+  }
+
+  private byte[] getDWithPackagePrivateFoo() throws NoSuchMethodException, IOException {
+    return transformer(D.class)
+        .setAccessFlags(D.class.getDeclaredMethod("bar", null), m -> m.unsetPublic())
+        .transform();
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      C d = (C) ((Object) new D());
+      A.run(d);
+      d.foo();
+      d.bar();
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
new file mode 100644
index 0000000..c2d041c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
@@ -0,0 +1,149 @@
+// Copyright (c) 2020, 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.resolution.packageprivate;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.a.Abstract;
+import com.android.tools.r8.resolution.packageprivate.a.I;
+import com.android.tools.r8.resolution.packageprivate.a.J;
+import com.android.tools.r8.resolution.packageprivate.a.NonAbstract;
+import com.android.tools.r8.resolution.packageprivate.a.NonAbstractExtendingA;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.transformers.ClassTransformer;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.MethodVisitor;
+
+@RunWith(Parameterized.class)
+public class PackagePrivateWithDefaultMethodTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public PackagePrivateWithDefaultMethodTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void testResolution() throws Exception {
+    assumeTrue(parameters.useRuntimeAsNoneRuntime());
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(
+            buildClasses(
+                    Abstract.class,
+                    I.class,
+                    A.class,
+                    NonAbstractExtendingA.class,
+                    J.class,
+                    Main.class)
+                .addClassProgramData(getNonAbstractWithoutDeclaredMethods())
+                .build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
+    DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
+    Set<String> targets =
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+            .map(DexEncodedMethod::qualifiedName)
+            .collect(Collectors.toSet());
+    // TODO(b/148591377): The set should be empty.
+    ImmutableSet<String> expected = ImmutableSet.of(Abstract.class.getTypeName() + ".foo");
+    assertEquals(expected, targets);
+  }
+
+  @Test
+  public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+    TestRunResult<?> runResult =
+        testForRuntime(parameters)
+            .addProgramClasses(
+                Abstract.class, I.class, A.class, NonAbstractExtendingA.class, J.class, Main.class)
+            .addProgramClassFileData(getNonAbstractWithoutDeclaredMethods())
+            .run(parameters.getRuntime(), Main.class);
+    if (parameters.isDexRuntime()
+        && parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+      runResult.assertFailure();
+    } else {
+      runResult.assertFailureWithErrorThatMatches(containsString("AbstractMethodError"));
+    }
+  }
+
+  @Test
+  public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+    R8TestRunResult runResult =
+        testForR8(parameters.getBackend())
+            .addProgramClasses(
+                Abstract.class, I.class, A.class, NonAbstractExtendingA.class, J.class, Main.class)
+            .addProgramClassFileData(getNonAbstractWithoutDeclaredMethods())
+            .setMinApi(parameters.getApiLevel())
+            .addKeepMainRule(Main.class)
+            .run(parameters.getRuntime(), Main.class);
+    if (parameters.isDexRuntime()
+        && parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+      runResult.assertFailure();
+    } else {
+      runResult.assertFailureWithErrorThatMatches(containsString("AbstractMethodError"));
+    }
+  }
+
+  private byte[] getNonAbstractWithoutDeclaredMethods() throws IOException {
+    return transformer(NonAbstract.class)
+        .addClassTransformer(
+            new ClassTransformer() {
+              @Override
+              public MethodVisitor visitMethod(
+                  int access,
+                  String name,
+                  String descriptor,
+                  String signature,
+                  String[] exceptions) {
+                if (!name.equals("foo")) {
+                  return super.visitMethod(access, name, descriptor, signature, exceptions);
+                }
+                return null;
+              }
+            })
+        .transform();
+  }
+
+  public static class A extends NonAbstract {}
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      NonAbstractExtendingA d = new NonAbstractExtendingA();
+      Abstract.run(d);
+      d.foo();
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
new file mode 100644
index 0000000..28c8c2f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
@@ -0,0 +1,120 @@
+// Copyright (c) 2020, 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.resolution.packageprivate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.a.A;
+import com.android.tools.r8.resolution.packageprivate.a.A.B;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class WidenAccessOutsidePackageTest extends TestBase {
+
+  private final TestParameters parameters;
+  private static final String[] EXPECTED = new String[] {"C.foo", "B.bar", "C.foo", "C.bar"};
+  private static final String[] EXPECTED_DALVIK = new String[] {"C.foo", "C.bar", "C.foo", "C.bar"};
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public WidenAccessOutsidePackageTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void testResolution() throws Exception {
+    assumeTrue(parameters.useRuntimeAsNoneRuntime());
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(
+            buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
+    DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
+    Set<String> targets =
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+            .map(DexEncodedMethod::qualifiedName)
+            .collect(Collectors.toSet());
+    // TODO(b/149363086): Fix expectation.
+    ImmutableSet<String> expected =
+        ImmutableSet.of(
+            A.class.getTypeName() + ".bar",
+            B.class.getTypeName() + ".bar",
+            C.class.getTypeName() + ".bar");
+    assertEquals(expected, targets);
+  }
+
+  @Test
+  public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+    TestRunResult<?> runResult =
+        testForRuntime(parameters)
+            .addProgramClasses(A.class, B.class, C.class, Main.class)
+            .run(parameters.getRuntime(), Main.class);
+    if (parameters.isDexRuntime()
+        && parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+      runResult.assertSuccessWithOutputLines(EXPECTED_DALVIK);
+    } else {
+      runResult.assertSuccessWithOutputLines(EXPECTED);
+    }
+  }
+
+  @Test
+  public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+    // TODO(b/149363086): Fix expectation.
+    testForR8(parameters.getBackend())
+        .addProgramClasses(A.class, B.class, C.class, Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED_DALVIK);
+  }
+
+  public static class C extends B {
+    @Override
+    public void foo() {
+      System.out.println("C.foo");
+    }
+
+    public void bar() {
+      System.out.println("C.bar");
+    }
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      C c = new C();
+      A.run(c);
+      c.foo();
+      c.bar();
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/A.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/A.java
new file mode 100644
index 0000000..8154e21
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/A.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+public class A {
+
+  protected void foo() {
+    System.out.println("A.foo");
+  }
+
+  void bar() {
+    System.out.println("A.bar");
+  }
+
+  public static class B extends A {
+
+    @Override
+    protected void foo() {
+      System.out.println("B.foo");
+    }
+
+    @Override
+    void bar() {
+      System.out.println("B.bar");
+    }
+  }
+
+  public static void run(A a) {
+    a.foo();
+    a.bar();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/Abstract.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/Abstract.java
new file mode 100644
index 0000000..bd4f5b2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/Abstract.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+public abstract class Abstract {
+
+  abstract void foo();
+
+  public static void run(Abstract a) {
+    a.foo();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/D.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/D.java
new file mode 100644
index 0000000..1d7c54e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/D.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+import com.android.tools.r8.resolution.packageprivate.PackagePrivateReentryTest.C;
+
+public class D extends C {
+  @Override
+  public void foo() {
+    System.out.println("D.foo");
+  }
+
+  @Override
+  public void bar() {
+    System.out.println("D.bar");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/I.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/I.java
new file mode 100644
index 0000000..a510f12
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/I.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+public interface I {
+
+  default void foo() {
+    System.out.println("I.foo");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/J.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/J.java
new file mode 100644
index 0000000..6f3d327
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/J.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+public interface J {
+
+  default void foo() {
+    System.out.println("J.foo");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstract.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstract.java
new file mode 100644
index 0000000..75e25a5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstract.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+public class NonAbstract extends Abstract implements I {
+
+  @Override
+  public void foo() {
+    System.out.println("Method declaration will be removed");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstractExtendingA.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstractExtendingA.java
new file mode 100644
index 0000000..4478062
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstractExtendingA.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, 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.resolution.packageprivate.a;
+
+import com.android.tools.r8.resolution.packageprivate.PackagePrivateWithDefaultMethodTest;
+
+public class NonAbstractExtendingA extends PackagePrivateWithDefaultMethodTest.A implements J {}
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
index 8a52035..9538dec 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.virtualtargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -46,13 +50,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     // TODO(b/148591377): Should we report B.foo()?
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
index 34b536b..4133fbe 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.virtualtargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -46,13 +50,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, A.class, B.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, A.class, B.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     // TODO(b/148591377): I.foo() should ideally not be included in the set.
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
index 399ad7d..264ddb0 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.virtualtargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -46,13 +50,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
index 4759dc3..ff58047 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.virtualtargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -46,16 +50,19 @@
   @Test
   public void testDynamicLookupTargets() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, J.class, Main.class)
-                    .addClassProgramData(setAImplementsIAndJ())
-                    .build(),
-                Main.class)
-            .appInfo();
+            buildClasses(I.class, J.class, Main.class)
+                .addClassProgramData(setAImplementsIAndJ())
+                .build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
index ebbfcef..055c113 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.virtualtargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -46,12 +50,15 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
-        computeAppViewWithLiveness(buildClasses(A.class, I.class, Main.class).build(), Main.class)
-            .appInfo();
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(buildClasses(A.class, I.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+    ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected = ImmutableSet.of(I.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
index e4d1f55..570527c 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.resolution.virtualtargets;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
@@ -47,14 +50,16 @@
   @Test
   public void testResolution() throws Exception {
     assumeTrue(parameters.useRuntimeAsNoneRuntime());
-    AppInfoWithLiveness appInfo =
+    AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
-                buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class)
-            .appInfo();
+            buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+    assertTrue(lookupResult.isLookupResultSuccess());
     Set<String> targets =
-        resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+        lookupResult.asLookupResultSuccess().getMethodTargets().stream()
             .map(DexEncodedMethod::qualifiedName)
             .collect(Collectors.toSet());
     ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java b/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java
index 725fe66..3971997 100644
--- a/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java
+++ b/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java
@@ -31,7 +31,7 @@
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().build();
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
   }
 
   private final TestParameters parameters;
@@ -46,7 +46,7 @@
         .addProgramClasses(TestClass.class)
         .addKeepMainRule(TestClass.class)
         .addKeepRules("-addconfigurationdebugging")
-        .setMinApi(parameters.getRuntime())
+        .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), TestClass.class)
         .assertSuccessWithOutput(StringUtils.lines("false"));
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java
index 0cf779d..3396686 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java
@@ -67,12 +67,12 @@
     MethodSubject methodWithLiveProgramAnnotationSubject =
         testClassSubject.uniqueMethodWithName("methodWithLiveProgramAnnotation");
     assertThat(methodWithLiveProgramAnnotationSubject, isPresent());
-    assertEquals(1, methodWithLiveProgramAnnotationSubject.getMethod().annotations.size());
+    assertEquals(1, methodWithLiveProgramAnnotationSubject.getMethod().annotations().size());
 
     MethodSubject methodWithDeadProgramAnnotationSubject =
         testClassSubject.uniqueMethodWithName("methodWithDeadProgramAnnotation");
     assertThat(methodWithDeadProgramAnnotationSubject, isPresent());
-    assertEquals(0, methodWithDeadProgramAnnotationSubject.getMethod().annotations.size());
+    assertEquals(0, methodWithDeadProgramAnnotationSubject.getMethod().annotations().size());
 
     result.assertSuccessWithOutputLines("@" + liveAnnotationClassSubject.getFinalName() + "()");
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java
index 58671ab..5a978c6 100644
--- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java
@@ -69,11 +69,11 @@
 
   private void inspect(CodeInspector inspector) {
     ClassSubject clazz = inspector.clazz(Main.class);
-    assertTrue(clazz.getDexClass().annotations.isEmpty());
+    assertTrue(clazz.getDexClass().annotations().isEmpty());
     MethodSubject main = clazz.uniqueMethodWithName("main");
-    assertTrue(main.getMethod().annotations.isEmpty());
+    assertTrue(main.getMethod().annotations().isEmpty());
     FieldSubject field = clazz.uniqueFieldWithName("field");
-    assertTrue(field.getField().annotations.isEmpty());
+    assertTrue(field.getField().annotations().isEmpty());
     assertTrue(clazz.getDexClass().sourceFile == null || clazz.getDexClass().sourceFile.size == 0);
     assertNull(main.getLineNumberTable());
     assertTrue(main.getLocalVariableTable().isEmpty());
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index 0c2358a..eb3929c 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -166,7 +166,7 @@
           }
         });
   }
-
+  
   /** Unconditionally replace the descriptor (ie, qualified name) of a class. */
   public ClassFileTransformer setClassDescriptor(String descriptor) {
     assert DescriptorUtils.isClassDescriptor(descriptor);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java
index 20da5d0..f41135f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java
@@ -95,4 +95,9 @@
   public AnnotationSubject annotation(String name) {
     return new AbsentAnnotationSubject();
   }
+
+  @Override
+  public String getJvmFieldSignatureAsString() {
+    return null;
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
index c72d305..5efcf6e 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.utils.codeinspector;
 
+import java.util.List;
 import kotlinx.metadata.jvm.JvmMethodSignature;
 
 public class AbsentKmFunctionSubject extends KmFunctionSubject {
@@ -38,6 +39,11 @@
   }
 
   @Override
+  public List<KmValueParameterSubject> valueParameters() {
+    return null;
+  }
+
+  @Override
   public KmTypeSubject returnType() {
     return null;
   }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java
index 70f6e52..d9c7d55 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java
@@ -29,6 +29,11 @@
   }
 
   @Override
+  public String name() {
+    return null;
+  }
+
+  @Override
   public JvmFieldSignature fieldSignature() {
     return null;
   }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
index b3e5eec..e08c9b7 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
@@ -132,4 +132,9 @@
   public AnnotationSubject annotation(String name) {
     return new AbsentAnnotationSubject();
   }
+
+  @Override
+  public String getJvmMethodSignatureAsString() {
+    return null;
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastCfInstructionSubject.java
new file mode 100644
index 0000000..0f5c42c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastCfInstructionSubject.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import com.android.tools.r8.cf.code.CfCheckCast;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.graph.DexType;
+
+public class CheckCastCfInstructionSubject extends CfInstructionSubject
+    implements CheckCastInstructionSubject {
+  public CheckCastCfInstructionSubject(CfInstruction instruction, MethodSubject method) {
+    super(instruction, method);
+    assert isCheckCast();
+  }
+
+  @Override
+  public DexType getType() {
+    return ((CfCheckCast) instruction).getType();
+  }
+
+  @Override
+  public CheckCastInstructionSubject asCheckCast() {
+    return this;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastDexInstructionSubject.java
new file mode 100644
index 0000000..ea10ad4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastDexInstructionSubject.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import com.android.tools.r8.code.CheckCast;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.graph.DexType;
+
+public class CheckCastDexInstructionSubject extends DexInstructionSubject
+    implements CheckCastInstructionSubject {
+  public CheckCastDexInstructionSubject(Instruction instruction, MethodSubject method) {
+    super(instruction, method);
+    assert isCheckCast();
+  }
+
+  @Override
+  public DexType getType() {
+    return ((CheckCast) instruction).getType();
+  }
+
+  @Override
+  public CheckCastInstructionSubject asCheckCast() {
+    return this;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastInstructionSubject.java
new file mode 100644
index 0000000..e7fa916
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastInstructionSubject.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import com.android.tools.r8.graph.DexType;
+
+public interface CheckCastInstructionSubject extends InstructionSubject {
+  DexType getType();
+}
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 5e1e668..63c85d5 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
@@ -354,6 +354,8 @@
       return new NewInstanceDexInstructionSubject(instruction, method);
     } else if (dexInst.isConstString(JumboStringMode.ALLOW)) {
       return new ConstStringDexInstructionSubject(instruction, method);
+    } else if (dexInst.isCheckCast()) {
+      return new CheckCastDexInstructionSubject(instruction, method);
     } else {
       return dexInst;
     }
@@ -369,6 +371,8 @@
       return new NewInstanceCfInstructionSubject(instruction, method);
     } else if (cfInst.isConstString(JumboStringMode.ALLOW)) {
       return new ConstStringCfInstructionSubject(instruction, method);
+    } else if (cfInst.isCheckCast()) {
+      return new CheckCastCfInstructionSubject(instruction, method);
     } else {
       return cfInst;
     }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
index dc9940f..957e78a 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
@@ -34,4 +34,6 @@
   public boolean isFieldSubject() {
     return true;
   }
+
+  public abstract String getJvmFieldSignatureAsString();
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index 3e83c5d..c0dba89 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -230,7 +230,7 @@
     assert !name.endsWith("EnclosingClass")
         && !name.endsWith("EnclosingMethod")
         && !name.endsWith("InnerClass");
-    DexAnnotation annotation = codeInspector.findAnnotation(name, dexClass.annotations);
+    DexAnnotation annotation = codeInspector.findAnnotation(name, dexClass.annotations());
     return annotation == null
         ? new AbsentAnnotationSubject()
         : new FoundAnnotationSubject(annotation);
@@ -296,12 +296,12 @@
   @Override
   public String getOriginalSignatureAttribute() {
     return codeInspector.getOriginalSignatureAttribute(
-        dexClass.annotations, GenericSignatureParser::parseClassSignature);
+        dexClass.annotations(), GenericSignatureParser::parseClassSignature);
   }
 
   @Override
   public String getFinalSignatureAttribute() {
-    return codeInspector.getFinalSignatureAttribute(dexClass.annotations);
+    return codeInspector.getFinalSignatureAttribute(dexClass.annotations());
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
index 7c40d1e..411dad2 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
@@ -134,17 +134,17 @@
   @Override
   public String getOriginalSignatureAttribute() {
     return codeInspector.getOriginalSignatureAttribute(
-        dexField.annotations, GenericSignatureParser::parseFieldSignature);
+        dexField.annotations(), GenericSignatureParser::parseFieldSignature);
   }
 
   @Override
   public String getFinalSignatureAttribute() {
-    return codeInspector.getFinalSignatureAttribute(dexField.annotations);
+    return codeInspector.getFinalSignatureAttribute(dexField.annotations());
   }
 
   @Override
   public AnnotationSubject annotation(String name) {
-    DexAnnotation annotation = codeInspector.findAnnotation(name, dexField.annotations);
+    DexAnnotation annotation = codeInspector.findAnnotation(name, dexField.annotations());
     return annotation == null
         ? new AbsentAnnotationSubject()
         : new FoundAnnotationSubject(annotation);
@@ -154,4 +154,9 @@
   public String toString() {
     return dexField.toSourceString();
   }
+
+  @Override
+  public String getJvmFieldSignatureAsString() {
+    return dexField.field.name.toString() + ":" + dexField.field.type.toDescriptorString();
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
index 3bbf235..28eff88 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
@@ -4,6 +4,8 @@
 package com.android.tools.r8.utils.codeinspector;
 
 import com.android.tools.r8.utils.codeinspector.FoundKmDeclarationContainerSubject.KmFunctionProcessor;
+import java.util.List;
+import java.util.stream.Collectors;
 import kotlinx.metadata.KmFunction;
 import kotlinx.metadata.KmType;
 import kotlinx.metadata.jvm.JvmMethodSignature;
@@ -56,6 +58,13 @@
   }
 
   @Override
+  public List<KmValueParameterSubject> valueParameters() {
+    return kmFunction.getValueParameters().stream()
+        .map(KmValueParameterSubject::new)
+        .collect(Collectors.toList());
+  }
+
+  @Override
   public KmTypeSubject returnType() {
     return new KmTypeSubject(kmFunction.getReturnType());
   }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java
index 4f9cc94..3cfe20d 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java
@@ -49,6 +49,11 @@
   }
 
   @Override
+  public String name() {
+    return kmProperty.getName();
+  }
+
+  @Override
   public JvmFieldSignature fieldSignature() {
     return fieldSignature;
   }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 1051e28..fe574e4 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -24,6 +24,7 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.naming.MemberNaming;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
@@ -32,6 +33,7 @@
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
@@ -177,7 +179,7 @@
   @Override
   public String getOriginalSignatureAttribute() {
     return codeInspector.getOriginalSignatureAttribute(
-        dexMethod.annotations, GenericSignatureParser::parseMethodSignature);
+        dexMethod.annotations(), GenericSignatureParser::parseMethodSignature);
   }
 
   public DexMethod getOriginalDexMethod(DexItemFactory dexItemFactory) {
@@ -191,7 +193,7 @@
 
   @Override
   public String getFinalSignatureAttribute() {
-    return codeInspector.getFinalSignatureAttribute(dexMethod.annotations);
+    return codeInspector.getFinalSignatureAttribute(dexMethod.annotations());
   }
 
   public Iterable<InstructionSubject> instructions() {
@@ -335,7 +337,7 @@
 
   @Override
   public AnnotationSubject annotation(String name) {
-    DexAnnotation annotation = codeInspector.findAnnotation(name, dexMethod.annotations);
+    DexAnnotation annotation = codeInspector.findAnnotation(name, dexMethod.annotations());
     return annotation == null
         ? new AbsentAnnotationSubject()
         : new FoundAnnotationSubject(annotation);
@@ -356,4 +358,15 @@
             .collect(Collectors.toList()),
         Reference.returnTypeFromDescriptor(method.proto.returnType.toDescriptorString()));
   }
+
+  @Override
+  public String getJvmMethodSignatureAsString() {
+    return dexMethod.method.name.toString()
+        + "("
+        + StringUtils.join(
+            Arrays.stream(dexMethod.method.proto.parameters.values)
+                .map(DexType::toDescriptorString).collect(Collectors.toList()), "")
+        + ")"
+        + dexMethod.method.proto.returnType.toDescriptorString();
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
index 9a48dfa..6eba32b 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
@@ -84,6 +84,10 @@
 
   boolean isCheckCast(String type);
 
+  default CheckCastInstructionSubject asCheckCast() {
+    return null;
+  }
+
   boolean isInstanceOf();
 
   boolean isInstanceOf(String type);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
index d0e0a37..161aa3f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.utils.codeinspector;
 
+import java.util.List;
 import kotlinx.metadata.KmFunction;
 import kotlinx.metadata.jvm.JvmMethodSignature;
 
@@ -18,5 +19,7 @@
 
   public abstract KmTypeSubject receiverParameterType();
 
+  public abstract List<KmValueParameterSubject> valueParameters();
+
   public abstract KmTypeSubject returnType();
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java
index 9fb5a0a..826c1f1 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java
@@ -15,6 +15,8 @@
 
   public abstract boolean isExtension();
 
+  public abstract String name();
+
   public abstract JvmFieldSignature fieldSignature();
 
   public abstract JvmMethodSignature getterSignature();
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmValueParameterSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmValueParameterSubject.java
new file mode 100644
index 0000000..1f96b7d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmValueParameterSubject.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import static kotlinx.metadata.Flag.ValueParameter.DECLARES_DEFAULT_VALUE;
+
+import com.android.tools.r8.errors.Unreachable;
+import kotlinx.metadata.KmValueParameter;
+
+public class KmValueParameterSubject extends Subject {
+  private final KmValueParameter kmValueParameter;
+
+  KmValueParameterSubject(KmValueParameter kmValueParameter) {
+    this.kmValueParameter = kmValueParameter;
+  }
+
+  public KmTypeSubject type() {
+    return new KmTypeSubject(kmValueParameter.getType());
+  }
+
+  public KmTypeSubject varargElementType() {
+    if (!isVararg()) {
+      return null;
+    }
+    return new KmTypeSubject(kmValueParameter.getVarargElementType());
+  }
+
+  public boolean isVararg() {
+    return kmValueParameter.getVarargElementType() != null;
+  }
+
+  public boolean declaresDefaultValue() {
+    return DECLARES_DEFAULT_VALUE.invoke(kmValueParameter.getFlags());
+  }
+
+  @Override
+  public boolean isPresent() {
+    return true;
+  }
+
+  @Override
+  public boolean isRenamed() {
+    throw new Unreachable("Cannot determine if a parameter is renamed");
+  }
+
+  @Override
+  public boolean isSynthetic() {
+    throw new Unreachable("Cannot determine if a parameter is synthetic");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
index af6e1a4..50911f3 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -104,4 +104,6 @@
   public boolean hasCode() {
     return getMethod().getCode() != null;
   }
+
+  public abstract String getJvmMethodSignatureAsString();
 }
diff --git a/tools/test.py b/tools/test.py
index 9359394..a75beb4 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -237,6 +237,7 @@
     gradle_args.append('-Pr8lib_no_deps')
   if options.worktree:
     gradle_args.append('-g=' + os.path.join(utils.REPO_ROOT, ".gradle_user_home"))
+    gradle_args.append('--no-daemon')
 
   # Build an R8 with dependencies for bootstrapping tests before adding test sources.
   gradle_args.append('r8WithRelocatedDeps')