Merge "Remove enclosing method attrs that reference pruned items."
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 61161bb..48c2cde 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -4,12 +4,12 @@
 package com.android.tools.r8;
 
 import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexDefinition;
 import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.graphinfo.GraphConsumer;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.MainDexClasses;
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
index a1a2837..a55033a 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graphinfo.GraphConsumer;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.ProguardConfigurationParser;
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 5c82a50..c1664a6 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.dex.Marker;
 import com.android.tools.r8.dex.Marker.Tool;
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
@@ -19,7 +20,6 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.graphinfo.GraphConsumer;
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.optimize.EnumOrdinalMapCollector;
 import com.android.tools.r8.ir.optimize.MethodPoolCollection;
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index e533101..39630f3 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -5,8 +5,8 @@
 
 import com.android.tools.r8.ProgramResource.Kind;
 import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graphinfo.GraphConsumer;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
 import com.android.tools.r8.origin.StandardOutOrigin;
diff --git a/src/main/java/com/android/tools/r8/graphinfo/AnnotationGraphNode.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/AnnotationGraphNode.java
similarity index 94%
rename from src/main/java/com/android/tools/r8/graphinfo/AnnotationGraphNode.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/AnnotationGraphNode.java
index c317293..5242510 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/AnnotationGraphNode.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/AnnotationGraphNode.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.Keep;
 
diff --git a/src/main/java/com/android/tools/r8/graphinfo/ClassGraphNode.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/ClassGraphNode.java
similarity index 94%
rename from src/main/java/com/android/tools/r8/graphinfo/ClassGraphNode.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/ClassGraphNode.java
index 41bd498..edbffbe 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/ClassGraphNode.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/ClassGraphNode.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.Keep;
 import com.android.tools.r8.references.ClassReference;
diff --git a/src/main/java/com/android/tools/r8/graphinfo/FieldGraphNode.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/FieldGraphNode.java
similarity index 94%
rename from src/main/java/com/android/tools/r8/graphinfo/FieldGraphNode.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/FieldGraphNode.java
index 9ae9a5b..b091613 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/FieldGraphNode.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/FieldGraphNode.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.Keep;
 import com.android.tools.r8.references.FieldReference;
diff --git a/src/main/java/com/android/tools/r8/graphinfo/GraphConsumer.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphConsumer.java
similarity index 91%
rename from src/main/java/com/android/tools/r8/graphinfo/GraphConsumer.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/GraphConsumer.java
index 8c124e5..3c7bda1 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/GraphConsumer.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphConsumer.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.KeepForSubclassing;
 
diff --git a/src/main/java/com/android/tools/r8/graphinfo/GraphEdgeInfo.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java
similarity index 95%
rename from src/main/java/com/android/tools/r8/graphinfo/GraphEdgeInfo.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java
index c0b3f3b..0c838ac 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/GraphEdgeInfo.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 public class GraphEdgeInfo {
 
diff --git a/src/main/java/com/android/tools/r8/graphinfo/GraphNode.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphNode.java
similarity index 92%
rename from src/main/java/com/android/tools/r8/graphinfo/GraphNode.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/GraphNode.java
index f248978..b99485a 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/GraphNode.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphNode.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.Keep;
 
diff --git a/src/main/java/com/android/tools/r8/graphinfo/KeepRuleGraphNode.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/KeepRuleGraphNode.java
similarity index 97%
rename from src/main/java/com/android/tools/r8/graphinfo/KeepRuleGraphNode.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/KeepRuleGraphNode.java
index 05a6e3d..7eb55a8 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/KeepRuleGraphNode.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/KeepRuleGraphNode.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.Keep;
 import com.android.tools.r8.origin.Origin;
diff --git a/src/main/java/com/android/tools/r8/graphinfo/MethodGraphNode.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/MethodGraphNode.java
similarity index 94%
rename from src/main/java/com/android/tools/r8/graphinfo/MethodGraphNode.java
rename to src/main/java/com/android/tools/r8/experimental/graphinfo/MethodGraphNode.java
index 494ddd4..94fe8e7 100644
--- a/src/main/java/com/android/tools/r8/graphinfo/MethodGraphNode.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/MethodGraphNode.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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.graphinfo;
+package com.android.tools.r8.experimental.graphinfo;
 
 import com.android.tools.r8.Keep;
 import com.android.tools.r8.references.MethodReference;
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLense.java b/src/main/java/com/android/tools/r8/graph/GraphLense.java
index 1c74f79..247a5fe 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLense.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLense.java
@@ -424,14 +424,30 @@
     return this == getIdentityLense();
   }
 
-  public <T extends DexDefinition> boolean assertDefinitionNotModified(Iterable<T> items) {
-    for (DexDefinition item : items) {
-      DexReference dexReference = item.toReference();
-      DexReference lookupedReference = lookupReference(dexReference);
+  public <T extends DexDefinition> boolean assertDefinitionsNotModified(Iterable<T> definitions) {
+    for (DexDefinition definition : definitions) {
+      DexReference reference = definition.toReference();
       // We allow changes to bridge methods as these get retargeted even if they are kept.
       boolean isBridge =
-          item.isDexEncodedMethod() && item.asDexEncodedMethod().accessFlags.isBridge();
-      assert isBridge || dexReference == lookupedReference;
+          definition.isDexEncodedMethod() && definition.asDexEncodedMethod().accessFlags.isBridge();
+      assert isBridge || lookupReference(reference) == reference;
+    }
+    return true;
+  }
+
+  public <T extends DexReference> boolean assertReferencesNotModified(Iterable<T> references) {
+    for (DexReference reference : references) {
+      if (reference.isDexField()) {
+        DexField field = reference.asDexField();
+        assert getRenamedFieldSignature(field) == field;
+      } else if (reference.isDexMethod()) {
+        DexMethod method = reference.asDexMethod();
+        assert getRenamedMethodSignature(method) == method;
+      } else {
+        assert reference.isDexType();
+        DexType type = reference.asDexType();
+        assert lookupType(type) == type;
+      }
     }
     return true;
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/CollectingGraphConsumer.java b/src/main/java/com/android/tools/r8/shaking/CollectingGraphConsumer.java
index 774a93a..27bdd95 100644
--- a/src/main/java/com/android/tools/r8/shaking/CollectingGraphConsumer.java
+++ b/src/main/java/com/android/tools/r8/shaking/CollectingGraphConsumer.java
@@ -3,9 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graphinfo.GraphConsumer;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo;
-import com.android.tools.r8.graphinfo.GraphNode;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
+import com.android.tools.r8.experimental.graphinfo.GraphNode;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.Map;
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 2ca33b0..95f077d 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -11,6 +11,15 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.experimental.graphinfo.AnnotationGraphNode;
+import com.android.tools.r8.experimental.graphinfo.ClassGraphNode;
+import com.android.tools.r8.experimental.graphinfo.FieldGraphNode;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo.EdgeKind;
+import com.android.tools.r8.experimental.graphinfo.GraphNode;
+import com.android.tools.r8.experimental.graphinfo.KeepRuleGraphNode;
+import com.android.tools.r8.experimental.graphinfo.MethodGraphNode;
 import com.android.tools.r8.graph.AppInfo.ResolutionResult;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
@@ -37,15 +46,6 @@
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.KeyedDexItem;
 import com.android.tools.r8.graph.PresortedComparable;
-import com.android.tools.r8.graphinfo.AnnotationGraphNode;
-import com.android.tools.r8.graphinfo.ClassGraphNode;
-import com.android.tools.r8.graphinfo.FieldGraphNode;
-import com.android.tools.r8.graphinfo.GraphConsumer;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo.EdgeKind;
-import com.android.tools.r8.graphinfo.GraphNode;
-import com.android.tools.r8.graphinfo.KeepRuleGraphNode;
-import com.android.tools.r8.graphinfo.MethodGraphNode;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.Invoke.Type;
@@ -2111,26 +2111,32 @@
       this.callSites = previous.callSites;
       this.brokenSuperInvokes = lense.rewriteMethodsConservatively(previous.brokenSuperInvokes);
       this.prunedTypes = rewriteItems(previous.prunedTypes, lense::lookupType);
-      assert lense.assertDefinitionNotModified(previous.noSideEffects.keySet());
+      assert lense.assertDefinitionsNotModified(previous.noSideEffects.keySet());
       this.noSideEffects = previous.noSideEffects;
-      assert lense.assertDefinitionNotModified(previous.assumedValues.keySet());
+      assert lense.assertDefinitionsNotModified(previous.assumedValues.keySet());
       this.assumedValues = previous.assumedValues;
-      assert lense.assertDefinitionNotModified(
-          previous.alwaysInline.stream().map(this::definitionFor).filter(Objects::nonNull)
+      assert lense.assertDefinitionsNotModified(
+          previous.alwaysInline.stream()
+              .map(this::definitionFor)
+              .filter(Objects::nonNull)
               .collect(Collectors.toList()));
       this.alwaysInline = previous.alwaysInline;
       this.forceInline = lense.rewriteMethodsWithRenamedSignature(previous.forceInline);
       this.neverInline = lense.rewriteMethodsWithRenamedSignature(previous.neverInline);
-      assert lense.assertDefinitionNotModified(
-          previous.neverMerge.stream().map(this::definitionFor).filter(Objects::nonNull)
+      assert lense.assertDefinitionsNotModified(
+          previous.neverMerge.stream()
+              .map(this::definitionFor)
+              .filter(Objects::nonNull)
               .collect(Collectors.toList()));
       this.neverClassInline = rewriteItems(previous.neverClassInline, lense::lookupType);
       this.neverMerge = previous.neverMerge;
       this.identifierNameStrings =
           lense.rewriteReferencesConservatively(previous.identifierNameStrings);
       // Switchmap classes should never be affected by renaming.
-      assert lense.assertDefinitionNotModified(
-          previous.switchMaps.keySet().stream().map(this::definitionFor).filter(Objects::nonNull)
+      assert lense.assertDefinitionsNotModified(
+          previous.switchMaps.keySet().stream()
+              .map(this::definitionFor)
+              .filter(Objects::nonNull)
               .collect(Collectors.toList()));
       this.switchMaps = previous.switchMaps;
       this.ordinalsMaps = rewriteKeys(previous.ordinalsMaps, lense::lookupType);
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepReason.java b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
index 82737a6..16d78a7 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepReason.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
@@ -3,12 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo.EdgeKind;
+import com.android.tools.r8.experimental.graphinfo.GraphNode;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo.EdgeKind;
-import com.android.tools.r8.graphinfo.GraphNode;
 
 // TODO(herhut): Canonicalize reason objects.
 public abstract class KeepReason {
@@ -50,7 +50,7 @@
   }
 
   public static KeepReason fieldReferencedIn(DexEncodedMethod method) {
-    return new ReferenedFrom(method);
+    return new ReferencedFrom(method);
   }
 
   public static KeepReason referencedInAnnotation(DexItem holder) {
@@ -219,9 +219,9 @@
     }
   }
 
-  private static class ReferenedFrom extends BasedOnOtherMethod {
+  private static class ReferencedFrom extends BasedOnOtherMethod {
 
-    private ReferenedFrom(DexEncodedMethod method) {
+    private ReferencedFrom(DexEncodedMethod method) {
       super(method);
     }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 33ee223..8d2c1b9 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -81,6 +81,10 @@
       // TODO(b/37137994): -outjars should be reported as errors, not just as warnings!
       "outjars");
 
+  private static final List<String> WARNED_OPTIONAL_SINGLE_ARG_OPTIONS = ImmutableList.of(
+      // TODO(b/121340442): we may support this later.
+      "dump");
+
   private static final List<String> WARNED_FLAG_OPTIONS = ImmutableList.of(
       // TODO(b/73707846): add support -addconfigurationdebugging
       "addconfigurationdebugging");
@@ -416,7 +420,11 @@
         if (option == null) {
           option = Iterables.find(WARNED_SINGLE_ARG_OPTIONS, this::skipOptionWithSingleArg, null);
           if (option == null) {
-            return false;
+            option = Iterables.find(
+                WARNED_OPTIONAL_SINGLE_ARG_OPTIONS, this::skipOptionWithOptionalSingleArg, null);
+            if (option == null) {
+              return false;
+            }
           }
         }
       }
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 0d69178..45ca1af 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -608,28 +608,67 @@
     timing.begin("fixup");
     GraphLense result = new TreeFixer().fixupTypeReferences(mergingGraphLense);
     timing.end();
-    assert result.assertDefinitionNotModified(
-        appInfo
-            .alwaysInline
-            .stream()
+    assert result.assertDefinitionsNotModified(
+        appInfo.alwaysInline.stream()
             .map(appInfo::definitionFor)
             .filter(Objects::nonNull)
             .collect(Collectors.toList()));
-    assert result.assertDefinitionNotModified(appInfo.noSideEffects.keySet());
-    // TODO(christofferqa): Enable this assert.
-    // assert result.assertNotModified(appInfo.pinnedItems);
-    assert verifyGraphLense(graphLense);
+    assert verifyGraphLense(result);
     return result;
   }
 
   private boolean verifyGraphLense(GraphLense graphLense) {
+    assert graphLense.assertDefinitionsNotModified(appInfo.noSideEffects.keySet());
+
+    // Note that the method assertReferencesNotModified() relies on getRenamedFieldSignature() and
+    // getRenamedMethodSignature() instead of lookupField() and lookupMethod(). This is important
+    // for this check to succeed, since it is not guaranteed that calling lookupMethod() with a
+    // pinned method will return the method itself.
+    //
+    // Consider the following example.
+    //
+    //   class A {
+    //     public void method() {}
+    //   }
+    //   class B extends A {
+    //     @Override
+    //     public void method() {}
+    //   }
+    //   class C extends B {
+    //     @Override
+    //     public void method() {}
+    //   }
+    //
+    // If A.method() is pinned, then A cannot be merged into B, but B can still be merged into C.
+    // Now, if there is an invoke-super instruction in C that hits B.method(), then this needs to
+    // be rewritten into an invoke-direct instruction. In particular, there could be an instruction
+    // `invoke-super A.method` in C. This would hit B.method(). Therefore, the graph lens records
+    // that `invoke-super A.method` instructions, which are in one of the methods from C, needs to
+    // be rewritten to `invoke-direct C.method$B`. This is valid even though A.method() is actually
+    // pinned, because this rewriting does not affect A.method() in any way.
+    assert graphLense.assertReferencesNotModified(appInfo.pinnedItems);
+
     for (DexProgramClass clazz : appInfo.classes()) {
       for (DexEncodedMethod encodedMethod : clazz.methods()) {
         DexMethod method = encodedMethod.method;
         DexMethod originalMethod = graphLense.getOriginalMethodSignature(method);
+        DexMethod renamedMethod = graphLense.getRenamedMethodSignature(originalMethod);
 
-        // Must be able to map back.
-        assert method == graphLense.getRenamedMethodSignature(originalMethod);
+        // Must be able to map back and forth.
+        if (encodedMethod.hasCode() && encodedMethod.getCode() instanceof SynthesizedBridgeCode) {
+          // For virtual methods, the vertical class merger creates two methods in the sub class
+          // in order to deal with invoke-super instructions (one that is private and one that is
+          // virtual). Therefore, it is not possible to go back and forth. Instead, we check that
+          // the two methods map back to the same original method, and that the original method
+          // can be mapped to the implementation method.
+          DexMethod implementationMethod =
+              ((SynthesizedBridgeCode) encodedMethod.getCode()).invocationTarget;
+          DexMethod originalImplementationMethod = graphLense.getOriginalMethodSignature(method);
+          assert originalMethod == originalImplementationMethod;
+          assert implementationMethod == renamedMethod;
+        } else {
+          assert method == renamedMethod;
+        }
 
         // Verify that all types are up-to-date. After vertical class merging, there should be no
         // more references to types that have been merged into another type.
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java
index 6b66465..20a05ab 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java
@@ -222,16 +222,32 @@
         Map<DexType, DexType> mergedClasses,
         DexItemFactory dexItemFactory,
         Map<DexProto, DexProto> cache) {
+      assert !signature.holder.isArrayType();
       DexType newHolder = mergedClasses.getOrDefault(signature.holder, signature.holder);
       DexProto newProto =
           dexItemFactory.applyClassMappingToProto(
-              signature.proto, type -> mergedClasses.getOrDefault(type, type), cache);
+              signature.proto,
+              type -> getTypeAfterClassMerging(type, mergedClasses, dexItemFactory),
+              cache);
       if (signature.holder.equals(newHolder) && signature.proto.equals(newProto)) {
         return signature;
       }
       return dexItemFactory.createMethod(newHolder, newProto, signature.name);
     }
 
+    private static DexType getTypeAfterClassMerging(
+        DexType type, Map<DexType, DexType> mergedClasses, DexItemFactory dexItemFactory) {
+      if (type.isArrayType()) {
+        DexType baseType = type.toBaseType(dexItemFactory);
+        DexType newBaseType = mergedClasses.getOrDefault(baseType, baseType);
+        if (newBaseType != baseType) {
+          return type.replaceBaseType(newBaseType, dexItemFactory);
+        }
+        return type;
+      }
+      return mergedClasses.getOrDefault(type, type);
+    }
+
     public boolean hasMappingForSignatureInContext(DexType context, DexMethod signature) {
       Map<DexMethod, GraphLenseLookupResult> virtualToDirectMethodMap =
           contextualVirtualToDirectMethodMaps.get(context);
diff --git a/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java b/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
index 11f2131..0572e88 100644
--- a/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
+++ b/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
@@ -4,14 +4,14 @@
 package com.android.tools.r8.shaking;
 
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graphinfo.ClassGraphNode;
-import com.android.tools.r8.graphinfo.FieldGraphNode;
-import com.android.tools.r8.graphinfo.GraphConsumer;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo.EdgeKind;
-import com.android.tools.r8.graphinfo.GraphNode;
-import com.android.tools.r8.graphinfo.KeepRuleGraphNode;
-import com.android.tools.r8.graphinfo.MethodGraphNode;
+import com.android.tools.r8.experimental.graphinfo.ClassGraphNode;
+import com.android.tools.r8.experimental.graphinfo.FieldGraphNode;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo.EdgeKind;
+import com.android.tools.r8.experimental.graphinfo.GraphNode;
+import com.android.tools.r8.experimental.graphinfo.KeepRuleGraphNode;
+import com.android.tools.r8.experimental.graphinfo.MethodGraphNode;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.Position;
 import com.android.tools.r8.position.TextPosition;
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 388cac3..90b9e18 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -14,11 +14,11 @@
 import com.android.tools.r8.dex.Marker;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.InvalidDebugInfoException;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 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.graphinfo.GraphConsumer;
 import com.android.tools.r8.ir.optimize.Inliner;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.ProguardConfiguration;
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
index 6d0ef5a..c5e44a3 100644
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
@@ -49,13 +49,16 @@
     Path mainDexList = temp.getRoot().toPath().resolve("maindexlist.txt");
     FileUtils.writeTextFile(mainDexList, "desugaringwithmissingclasstest1/Main.class");
 
+    // It is important to place the api usage sample jar after the current classpath because we want
+    // to find D8/R8 classes before the ones in the jar, otherwise renamed classes and fields cannot
+    // be found.
+    String classPath = System.getProperty("java.class.path") + File.pathSeparator + jar.toString();
     List<String> command =
         ImmutableList.<String>builder()
             .addAll(
                 ImmutableList.of(
                     ToolHelper.getJavaExecutable(),
-                    "-cp",
-                    jar.toString() + File.pathSeparator + System.getProperty("java.class.path"),
+                    "-cp", classPath,
                     main,
                     // Compiler arguments.
                     "--output",
diff --git a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
index d8d983f..35dafae 100644
--- a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
+++ b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
@@ -283,7 +283,7 @@
           .put(
               "lang.ClassLoader.getSystemResourceAsStreamLjava_lang_String.ClassLoader_getSystemResourceAsStream_A01",
               anyDexVm())
-          .put("lang.ClassLoader.getPackages.ClassLoader_getPackages_A01", any())
+          .put("lang.ClassLoader.getPackages.ClassLoader_getPackages_A01", anyDexVm())
           .put(
               "lang.ClassLoader.setClassAssertionStatusLjava_lang_StringZ.ClassLoader_setClassAssertionStatus_A01",
               any())
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 8c4f682..8afe46b 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -6,7 +6,7 @@
 import com.android.tools.r8.R8Command.Builder;
 import com.android.tools.r8.TestBase.Backend;
 import com.android.tools.r8.TestBase.R8Mode;
-import com.android.tools.r8.graphinfo.GraphConsumer;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingTest.java
index c7a8ef2..b8c4b47 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingTest.java
@@ -22,7 +22,6 @@
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class KotlinLambdaMergingTest extends AbstractR8KotlinTestBase {
@@ -455,7 +454,6 @@
     });
   }
 
-  @Ignore("b/121107286: assertion failure in VerticalClassMerger#verifyGraphLense")
   @Test
   public void testSingleton() throws Exception {
     final String mainClassName = "lambdas_singleton.MainKt";
diff --git a/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java b/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java
index 3eed543..0acd733 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graphinfo.GraphConsumer;
+import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index de10b45..ff84486 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -1851,6 +1851,30 @@
   }
 
   @Test
+  public void parse_dump_withoutFile() throws Exception {
+    Path proguardConfig = writeTextToTempFile(
+        "-dump"
+    );
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+    parser.parse(proguardConfig);
+    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
+        "Ignoring", "-dump");
+  }
+
+  @Test
+  public void parse_dump_withFile() throws Exception {
+    Path proguardConfig = writeTextToTempFile(
+        "-dump class_files.txt"
+    );
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+    parser.parse(proguardConfig);
+    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
+        "Ignoring", "-dump");
+  }
+
+  @Test
   public void parse_android() throws Exception {
     Path proguardConfig = writeTextToTempFile(
         "-android"
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java
index 871f76d..49679c4 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/applymapping/IfRuleWithApplyMappingTest.java
@@ -9,28 +9,22 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.nio.file.Path;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
+import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
 
 public class IfRuleWithApplyMappingTest extends TestBase {
 
-  @ClassRule
-  public static TemporaryFolder tempFolder = ToolHelper.getTemporaryFolderForTest();
-
   private static Path mappingFile;
 
-  @BeforeClass
-  public static void setup() throws Exception {
+  @Before
+  public void setup() throws Exception {
     // Mapping file that describes that Runnable has been renamed to A.
-    mappingFile = tempFolder.newFolder().toPath().resolve("mapping.txt");
+    mappingFile = temp.newFolder().toPath().resolve("mapping.txt");
     FileUtils.writeTextFile(
         mappingFile, Runnable.class.getTypeName() + " -> " + A.class.getTypeName() + ":");
   }
@@ -45,7 +39,7 @@
             "-keep class " + IfRuleWithApplyMappingTestClass.class.getTypeName() + " {",
             "  public void method(" + Runnable.class.getTypeName() + ");",
             "}",
-            "-applymapping " + mappingFile)
+            "-applymapping " + mappingFile.toAbsolutePath())
         .compile()
         .inspect(this::inspect);
   }
@@ -61,7 +55,7 @@
             "-keep class " + IfRuleWithApplyMappingTestClass.class.getTypeName() + " {",
             "  public void method(" + Runnable.class.getTypeName() + ");",
             "}",
-            "-applymapping " + mappingFile)
+            "-applymapping " + mappingFile.toAbsolutePath())
         .compile()
         .inspect(this::inspect);
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTest.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTest.java
index 689d3b6..35083c7 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTest.java
@@ -19,6 +19,9 @@
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 class Main {
 
@@ -37,9 +40,19 @@
   }
 }
 
+@RunWith(Parameterized.class)
 public class KeptMethodTest extends TestBase {
 
-  final Backend backend = Backend.DEX;
+  private final Backend backend;
+
+  @Parameters(name = "{0}")
+  public static Backend[] data() {
+    return Backend.values();
+  }
+
+  public KeptMethodTest(Backend backend) {
+    this.backend = backend;
+  }
 
   @Test
   public void testKeptMethod()
diff --git a/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java b/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
index 454d1f5..b138e50 100644
--- a/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
@@ -4,11 +4,11 @@
 package com.android.tools.r8.utils.graphinspector;
 
 import com.android.tools.r8.errors.Unimplemented;
-import com.android.tools.r8.graphinfo.ClassGraphNode;
-import com.android.tools.r8.graphinfo.FieldGraphNode;
-import com.android.tools.r8.graphinfo.GraphEdgeInfo;
-import com.android.tools.r8.graphinfo.GraphNode;
-import com.android.tools.r8.graphinfo.MethodGraphNode;
+import com.android.tools.r8.experimental.graphinfo.ClassGraphNode;
+import com.android.tools.r8.experimental.graphinfo.FieldGraphNode;
+import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
+import com.android.tools.r8.experimental.graphinfo.GraphNode;
+import com.android.tools.r8.experimental.graphinfo.MethodGraphNode;
 import com.android.tools.r8.references.ClassReference;
 import com.android.tools.r8.references.FieldReference;
 import com.android.tools.r8.references.MethodReference;