Prepare for applying the graph lens to dex instructions in the writer

Change-Id: I1e62b9ea64a877dc2a9a793413e6cb6561941716
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 99ff6a7..639120b 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -284,9 +284,7 @@
           namingLens = NamingLens.getIdentityLens();
         }
         new ApplicationWriter(
-                appView.appInfo().app(),
                 appView,
-                options,
                 marker == null ? null : ImmutableList.copyOf(markers),
                 GraphLens.getIdentityLens(),
                 InitClassLens.getDefault(),
@@ -307,7 +305,7 @@
   }
 
   private static DexApplication rewriteNonDexInputs(
-      AppView<?> appView,
+      AppView<AppInfo> appView,
       AndroidApp inputApp,
       InternalOptions options,
       ExecutorService executor,
@@ -333,6 +331,7 @@
       }
     }
     DexApplication cfApp = app.builder().replaceProgramClasses(nonDexProgramClasses).build();
+    appView.setAppInfo(new AppInfo(cfApp, appView.appInfo().getSyntheticItems().commit(cfApp)));
     ConvertedCfFiles convertedCfFiles = new ConvertedCfFiles();
     NamingLens prefixRewritingNamingLens =
         PrefixRewritingNamingLens.createPrefixRewritingNamingLens(appView);
@@ -340,9 +339,7 @@
         .run(appView.appInfo().classes(), executor);
     new KotlinMetadataRewriter(appView, prefixRewritingNamingLens).runForD8(executor);
     new ApplicationWriter(
-            cfApp,
             appView,
-            options,
             null,
             GraphLens.getIdentityLens(),
             InitClassLens.getDefault(),
diff --git a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
index 49ab77b..ff8aabb 100644
--- a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
+++ b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
@@ -99,9 +99,7 @@
         assert !options.hasMethodsFilter();
         ApplicationWriter writer =
             new ApplicationWriter(
-                appView.appInfo().app(),
-                null,
-                options,
+                appView,
                 markers,
                 GraphLens.getIdentityLens(),
                 InitClassLens.getDefault(),
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index 9935d84..21fc371 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -99,9 +99,7 @@
 
         try {
           new ApplicationWriter(
-                  appView.appInfo().app(),
                   appView,
-                  options,
                   markers,
                   GraphLens.getIdentityLens(),
                   InitClassLens.getDefault(),
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 3a9b0d9..d2078fd 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -231,9 +231,7 @@
             .write(options.getClassFileConsumer());
       } else {
         new ApplicationWriter(
-                appView.appInfo().app(),
                 appView,
-                options,
                 // Ensure that the marker for this compilation is the first in the list.
                 ImmutableList.<Marker>builder().add(marker).addAll(markers).build(),
                 graphLens,
diff --git a/src/main/java/com/android/tools/r8/bisect/Bisect.java b/src/main/java/com/android/tools/r8/bisect/Bisect.java
index 80dd656..0dcca76 100644
--- a/src/main/java/com/android/tools/r8/bisect/Bisect.java
+++ b/src/main/java/com/android/tools/r8/bisect/Bisect.java
@@ -189,9 +189,7 @@
     AndroidAppConsumers compatSink = new AndroidAppConsumers(options);
     ApplicationWriter writer =
         new ApplicationWriter(
-            app,
             AppView.createForD8(AppInfo.createInitialAppInfo(app)),
-            options,
             null,
             null,
             InitClassLens.getDefault(),
diff --git a/src/main/java/com/android/tools/r8/code/CheckCast.java b/src/main/java/com/android/tools/r8/code/CheckCast.java
index 569b358..ccb3db9 100644
--- a/src/main/java/com/android/tools/r8/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/code/CheckCast.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class CheckCast extends Format21c<DexType> {
 
@@ -39,7 +42,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/ConstClass.java b/src/main/java/com/android/tools/r8/code/ConstClass.java
index 2f8f7db..6c7a32f 100644
--- a/src/main/java/com/android/tools/r8/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/code/ConstClass.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class ConstClass extends Format21c<DexType> {
 
@@ -39,7 +42,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java b/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java
index 8518946..24370bf 100644
--- a/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java
@@ -6,11 +6,14 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.InternalCompilerError;
 import com.android.tools.r8.graph.DexMethodHandle;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -64,16 +67,25 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     int index = BBBB.getOffset(mapping);
     if (index != (index & 0xffff)) {
       throw new InternalCompilerError("MethodHandle-index overflow.");
     }
-    super.write(dest, mapping);
+    super.write(dest, context, graphLens, mapping, rewriter);
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getMethodHandle().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/code/ConstMethodType.java
index 8eb5443..6d6d99d 100644
--- a/src/main/java/com/android/tools/r8/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/code/ConstMethodType.java
@@ -6,10 +6,13 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.InternalCompilerError;
 import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -62,16 +65,25 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     int index = BBBB.getOffset(mapping);
     if (index != (index & 0xffff)) {
       throw new InternalCompilerError("MethodType-index overflow.");
     }
-    super.write(dest, mapping);
+    super.write(dest, context, graphLens, mapping, rewriter);
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getMethodType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/ConstString.java b/src/main/java/com/android/tools/r8/code/ConstString.java
index 261016b..8bccec9 100644
--- a/src/main/java/com/android/tools/r8/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/code/ConstString.java
@@ -6,9 +6,12 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.InternalCompilerError;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -31,7 +34,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getString().collectIndexedItems(indexedItems);
   }
 
@@ -71,12 +78,17 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     int index = BBBB.getOffset(mapping);
     if (index != (index & 0xffff)) {
       throw new InternalCompilerError("String-index overflow.");
     }
-    super.write(dest, mapping);
+    super.write(dest, context, graphLens, mapping, rewriter);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/code/DexInitClass.java b/src/main/java/com/android/tools/r8/code/DexInitClass.java
index 20f2047..9af799b 100644
--- a/src/main/java/com/android/tools/r8/code/DexInitClass.java
+++ b/src/main/java/com/android/tools/r8/code/DexInitClass.java
@@ -8,10 +8,13 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.FieldMemberType;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -36,7 +39,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     DexField field = indexedItems.getInitClassLens().getInitClassField(clazz);
     field.collectIndexedItems(indexedItems);
   }
@@ -91,7 +98,12 @@
   }
 
   @Override
-  public void write(ShortBuffer buffer, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer buffer,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     DexField field = mapping.getClinitField(clazz);
     writeFirst(dest, buffer, getOpcode(field));
     write16BitReference(field, buffer, mapping);
diff --git a/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java
index 1fb6e8c..c50bba8 100644
--- a/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java
@@ -6,9 +6,12 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
 import java.nio.ShortBuffer;
@@ -35,7 +38,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getItem().collectIndexedItems(indexedItems);
   }
 
@@ -78,7 +85,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     throw new Unreachable(
         "DexItemBasedConstString instructions should always be rewritten into ConstString");
   }
diff --git a/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java b/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java
index 36338f9..ff546af 100644
--- a/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java
+++ b/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java
@@ -3,8 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.code;
 
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -42,7 +45,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(3, dest);  // Pseudo-opcode = 0x0300
     write16BitValue(element_width, dest);
     write32BitValue(size, dest);
diff --git a/src/main/java/com/android/tools/r8/code/FilledNewArray.java b/src/main/java/com/android/tools/r8/code/FilledNewArray.java
index 1932e16..6a885d5 100644
--- a/src/main/java/com/android/tools/r8/code/FilledNewArray.java
+++ b/src/main/java/com/android/tools/r8/code/FilledNewArray.java
@@ -5,8 +5,11 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class FilledNewArray extends Format35c<DexType> {
 
@@ -38,7 +41,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java b/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java
index 7fc2adc..9d809d4 100644
--- a/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java
+++ b/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java
@@ -5,8 +5,11 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class FilledNewArrayRange extends Format3rc<DexType> {
 
@@ -38,7 +41,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/Format10t.java b/src/main/java/com/android/tools/r8/code/Format10t.java
index 4c61fa3..d34ecb2 100644
--- a/src/main/java/com/android/tools/r8/code/Format10t.java
+++ b/src/main/java/com/android/tools/r8/code/Format10t.java
@@ -4,7 +4,10 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -25,7 +28,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
   }
 
@@ -53,7 +61,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format10x.java b/src/main/java/com/android/tools/r8/code/Format10x.java
index 8eed571..6ffc866 100644
--- a/src/main/java/com/android/tools/r8/code/Format10x.java
+++ b/src/main/java/com/android/tools/r8/code/Format10x.java
@@ -4,7 +4,10 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -20,7 +23,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(0, dest);
   }
 
@@ -45,7 +53,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format11n.java b/src/main/java/com/android/tools/r8/code/Format11n.java
index f2b8ac2..933beba 100644
--- a/src/main/java/com/android/tools/r8/code/Format11n.java
+++ b/src/main/java/com/android/tools/r8/code/Format11n.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -34,7 +37,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(B, A, dest);
   }
 
@@ -58,7 +66,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format11x.java b/src/main/java/com/android/tools/r8/code/Format11x.java
index 318bf04..5d627bd 100644
--- a/src/main/java/com/android/tools/r8/code/Format11x.java
+++ b/src/main/java/com/android/tools/r8/code/Format11x.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -25,7 +28,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
   }
 
@@ -53,7 +61,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format12x.java b/src/main/java/com/android/tools/r8/code/Format12x.java
index ac90623..36284b9 100644
--- a/src/main/java/com/android/tools/r8/code/Format12x.java
+++ b/src/main/java/com/android/tools/r8/code/Format12x.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -28,7 +31,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(B, A, dest);
   }
 
@@ -57,7 +65,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format20t.java b/src/main/java/com/android/tools/r8/code/Format20t.java
index f145476..42d172a 100644
--- a/src/main/java/com/android/tools/r8/code/Format20t.java
+++ b/src/main/java/com/android/tools/r8/code/Format20t.java
@@ -4,7 +4,10 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -24,7 +27,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(0, dest);
     write16BitValue(AAAA, dest);
   }
@@ -53,7 +61,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format21c.java b/src/main/java/com/android/tools/r8/code/Format21c.java
index 04848f0..9118072 100644
--- a/src/main/java/com/android/tools/r8/code/Format21c.java
+++ b/src/main/java/com/android/tools/r8/code/Format21c.java
@@ -4,8 +4,11 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 import java.util.function.BiPredicate;
@@ -29,7 +32,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitReference(BBBB, dest, mapping);
   }
diff --git a/src/main/java/com/android/tools/r8/code/Format21h.java b/src/main/java/com/android/tools/r8/code/Format21h.java
index 221dc9e..848990d 100644
--- a/src/main/java/com/android/tools/r8/code/Format21h.java
+++ b/src/main/java/com/android/tools/r8/code/Format21h.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import java.nio.ShortBuffer;
 
 abstract class Format21h extends Base2Format {
@@ -28,7 +31,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitValue(BBBB, dest);
   }
@@ -48,7 +56,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format21s.java b/src/main/java/com/android/tools/r8/code/Format21s.java
index a9d7dc1..31c4bc9 100644
--- a/src/main/java/com/android/tools/r8/code/Format21s.java
+++ b/src/main/java/com/android/tools/r8/code/Format21s.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -30,7 +33,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitValue(BBBB, dest);
   }
@@ -60,7 +68,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format21t.java b/src/main/java/com/android/tools/r8/code/Format21t.java
index d89b029..5e52bac 100644
--- a/src/main/java/com/android/tools/r8/code/Format21t.java
+++ b/src/main/java/com/android/tools/r8/code/Format21t.java
@@ -5,10 +5,13 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.If.Type;
 import com.android.tools.r8.ir.code.ValueTypeConstraint;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -32,7 +35,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitValue(BBBB, dest);
   }
@@ -78,7 +86,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format22b.java b/src/main/java/com/android/tools/r8/code/Format22b.java
index 3952eb7..48955dc 100644
--- a/src/main/java/com/android/tools/r8/code/Format22b.java
+++ b/src/main/java/com/android/tools/r8/code/Format22b.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -34,7 +37,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitValue(combineBytes(CC, BB), dest);
   }
@@ -65,7 +73,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format22c.java b/src/main/java/com/android/tools/r8/code/Format22c.java
index 751ef61..6107159 100644
--- a/src/main/java/com/android/tools/r8/code/Format22c.java
+++ b/src/main/java/com/android/tools/r8/code/Format22c.java
@@ -4,8 +4,11 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 import java.util.function.BiPredicate;
@@ -33,7 +36,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(B, A, dest);
     write16BitReference(CCCC, dest, mapping);
   }
diff --git a/src/main/java/com/android/tools/r8/code/Format22s.java b/src/main/java/com/android/tools/r8/code/Format22s.java
index 25c51d6..1b9aeb4 100644
--- a/src/main/java/com/android/tools/r8/code/Format22s.java
+++ b/src/main/java/com/android/tools/r8/code/Format22s.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -34,7 +37,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(B, A, dest);
     write16BitValue(CCCC, dest);
   }
@@ -65,7 +73,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format22t.java b/src/main/java/com/android/tools/r8/code/Format22t.java
index 6505e5c..4e75d23 100644
--- a/src/main/java/com/android/tools/r8/code/Format22t.java
+++ b/src/main/java/com/android/tools/r8/code/Format22t.java
@@ -5,10 +5,13 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.If.Type;
 import com.android.tools.r8.ir.code.ValueTypeConstraint;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -36,7 +39,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(B, A, dest);
     write16BitValue(CCCC, dest);
   }
@@ -82,7 +90,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format22x.java b/src/main/java/com/android/tools/r8/code/Format22x.java
index 5c1b2c4..901af1e 100644
--- a/src/main/java/com/android/tools/r8/code/Format22x.java
+++ b/src/main/java/com/android/tools/r8/code/Format22x.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -29,7 +32,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitValue(BBBB, dest);
   }
@@ -59,7 +67,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format23x.java b/src/main/java/com/android/tools/r8/code/Format23x.java
index 739b66f..e9d030b 100644
--- a/src/main/java/com/android/tools/r8/code/Format23x.java
+++ b/src/main/java/com/android/tools/r8/code/Format23x.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -33,7 +36,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitValue(combineBytes(CC, BB), dest);
   }
@@ -63,7 +71,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format30t.java b/src/main/java/com/android/tools/r8/code/Format30t.java
index bfcf0d3..dcf5064 100644
--- a/src/main/java/com/android/tools/r8/code/Format30t.java
+++ b/src/main/java/com/android/tools/r8/code/Format30t.java
@@ -4,7 +4,10 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -23,7 +26,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(0, dest);
     write32BitValue(AAAAAAAA, dest);
   }
@@ -52,7 +60,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format31c.java b/src/main/java/com/android/tools/r8/code/Format31c.java
index ead4920..023aeac 100644
--- a/src/main/java/com/android/tools/r8/code/Format31c.java
+++ b/src/main/java/com/android/tools/r8/code/Format31c.java
@@ -7,8 +7,11 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 import java.util.function.BiPredicate;
@@ -32,7 +35,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write32BitReference(BBBBBBBB, dest, mapping);
   }
@@ -58,7 +66,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     BBBBBBBB.collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/Format31i.java b/src/main/java/com/android/tools/r8/code/Format31i.java
index 5e55ca4..843319b 100644
--- a/src/main/java/com/android/tools/r8/code/Format31i.java
+++ b/src/main/java/com/android/tools/r8/code/Format31i.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -28,7 +31,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write32BitValue(BBBBBBBB, dest);
   }
@@ -53,7 +61,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format31t.java b/src/main/java/com/android/tools/r8/code/Format31t.java
index d650fed..9c7fdfd 100644
--- a/src/main/java/com/android/tools/r8/code/Format31t.java
+++ b/src/main/java/com/android/tools/r8/code/Format31t.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -28,7 +31,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     assert (getOffset() + BBBBBBBB) % 2 == 0;
     write32BitValue(BBBBBBBB, dest);
@@ -68,7 +76,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format32x.java b/src/main/java/com/android/tools/r8/code/Format32x.java
index a31a494..34ecf4f 100644
--- a/src/main/java/com/android/tools/r8/code/Format32x.java
+++ b/src/main/java/com/android/tools/r8/code/Format32x.java
@@ -6,7 +6,10 @@
 import static com.android.tools.r8.dex.Constants.U16BIT_MAX;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -30,7 +33,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(0, dest);
     write16BitValue(AAAA, dest);
     write16BitValue(BBBB, dest);
@@ -61,7 +69,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/Format35c.java b/src/main/java/com/android/tools/r8/code/Format35c.java
index fba7d0d..1ea8abd 100644
--- a/src/main/java/com/android/tools/r8/code/Format35c.java
+++ b/src/main/java/com/android/tools/r8/code/Format35c.java
@@ -4,8 +4,11 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 import java.util.function.BiPredicate;
@@ -51,7 +54,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(A, G, dest);
     write16BitReference(BBBB, dest, mapping);
     write16BitValue(combineBytes(makeByte(F, E), makeByte(D, C)), dest);
diff --git a/src/main/java/com/android/tools/r8/code/Format3rc.java b/src/main/java/com/android/tools/r8/code/Format3rc.java
index a50a9d9..27a3465 100644
--- a/src/main/java/com/android/tools/r8/code/Format3rc.java
+++ b/src/main/java/com/android/tools/r8/code/Format3rc.java
@@ -4,8 +4,11 @@
 package com.android.tools.r8.code;
 
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 import java.util.function.BiPredicate;
@@ -37,7 +40,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitReference(BBBB, dest, mapping);
     write16BitValue(CCCC, dest);
diff --git a/src/main/java/com/android/tools/r8/code/Format45cc.java b/src/main/java/com/android/tools/r8/code/Format45cc.java
index f5123cf..fad2d70 100644
--- a/src/main/java/com/android/tools/r8/code/Format45cc.java
+++ b/src/main/java/com/android/tools/r8/code/Format45cc.java
@@ -8,8 +8,11 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -87,13 +90,22 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     BBBB.collectIndexedItems(indexedItems);
     HHHH.collectIndexedItems(indexedItems);
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(A, G, dest);
     write16BitReference(BBBB, dest, mapping);
     write16BitValue(combineBytes(makeByte(F, E), makeByte(D, C)), dest);
diff --git a/src/main/java/com/android/tools/r8/code/Format4rcc.java b/src/main/java/com/android/tools/r8/code/Format4rcc.java
index 0ec2780..591e8be 100644
--- a/src/main/java/com/android/tools/r8/code/Format4rcc.java
+++ b/src/main/java/com/android/tools/r8/code/Format4rcc.java
@@ -7,8 +7,11 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 import java.util.function.BiPredicate;
@@ -40,7 +43,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write16BitReference(BBBB, dest, mapping);
     write16BitValue(CCCC, dest);
@@ -93,7 +101,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     BBBB.collectIndexedItems(indexedItems);
     HHHH.collectIndexedItems(indexedItems);
   }
diff --git a/src/main/java/com/android/tools/r8/code/Format51l.java b/src/main/java/com/android/tools/r8/code/Format51l.java
index 0e9ad93..face456 100644
--- a/src/main/java/com/android/tools/r8/code/Format51l.java
+++ b/src/main/java/com/android/tools/r8/code/Format51l.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import java.nio.ShortBuffer;
 
@@ -28,7 +31,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(AA, dest);
     write64BitValue(BBBBBBBBBBBBBBBB, dest);
   }
@@ -53,7 +61,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     // No references.
   }
 }
diff --git a/src/main/java/com/android/tools/r8/code/IgetOrIput.java b/src/main/java/com/android/tools/r8/code/IgetOrIput.java
index 7800ace..5b69be7 100644
--- a/src/main/java/com/android/tools/r8/code/IgetOrIput.java
+++ b/src/main/java/com/android/tools/r8/code/IgetOrIput.java
@@ -5,6 +5,9 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public abstract class IgetOrIput extends Format22c<DexField> {
 
@@ -17,7 +20,11 @@
   }
 
   @Override
-  public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public final void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getField().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/InstanceOf.java b/src/main/java/com/android/tools/r8/code/InstanceOf.java
index 05a9558..5e3d860 100644
--- a/src/main/java/com/android/tools/r8/code/InstanceOf.java
+++ b/src/main/java/com/android/tools/r8/code/InstanceOf.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class InstanceOf extends Format22c<DexType> {
 
@@ -49,7 +52,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index d8accd7..93fce2f 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -9,10 +9,13 @@
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -309,9 +312,18 @@
     return toString(null);
   }
 
-  public abstract void write(ShortBuffer buffer, ObjectToOffsetMapping mapping);
+  public abstract void write(
+      ShortBuffer buffer,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter);
 
-  public abstract void collectIndexedItems(IndexedItemCollection indexedItems);
+  public abstract void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter);
 
   public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
     // In the default case, there is nothing to substitute.
diff --git a/src/main/java/com/android/tools/r8/code/InvokeCustom.java b/src/main/java/com/android/tools/r8/code/InvokeCustom.java
index 72d0adb..67420a6 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeCustom.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexCallSite;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class InvokeCustom extends Format35c<DexCallSite> {
 
@@ -39,7 +42,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getCallSite().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java b/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java
index ae63c4d..3d5cadd 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexCallSite;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class InvokeCustomRange extends Format3rc<DexCallSite> {
 
@@ -39,7 +42,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getCallSite().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/code/InvokeMethod.java
index cab1eac..e54835f 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeMethod.java
@@ -5,6 +5,9 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public abstract class InvokeMethod extends Format35c<DexMethod> {
 
@@ -17,7 +20,11 @@
   }
 
   @Override
-  public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public final void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getMethod().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java b/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java
index 25fad42..f9f69e3 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java
@@ -5,6 +5,9 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public abstract class InvokeMethodRange extends Format3rc<DexMethod> {
 
@@ -17,7 +20,11 @@
   }
 
   @Override
-  public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public final void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getMethod().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/NewArray.java b/src/main/java/com/android/tools/r8/code/NewArray.java
index dfb4ccb..c02194a 100644
--- a/src/main/java/com/android/tools/r8/code/NewArray.java
+++ b/src/main/java/com/android/tools/r8/code/NewArray.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class NewArray extends Format22c<DexType> {
 
@@ -39,7 +42,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/NewInstance.java b/src/main/java/com/android/tools/r8/code/NewInstance.java
index 695ae96..024cc22 100644
--- a/src/main/java/com/android/tools/r8/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/code/NewInstance.java
@@ -5,9 +5,12 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 public class NewInstance extends Format21c<DexType> {
 
@@ -39,7 +42,11 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getType().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java b/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
index 110f668..c7caf43 100644
--- a/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
+++ b/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
@@ -3,7 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.code;
 
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -38,7 +41,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(1, dest);  // Pseudo-opcode = 0x0100
     write16BitValue(size, dest);
     write32BitValue(first_key, dest);
diff --git a/src/main/java/com/android/tools/r8/code/SgetOrSput.java b/src/main/java/com/android/tools/r8/code/SgetOrSput.java
index d04e098..338d5a0 100644
--- a/src/main/java/com/android/tools/r8/code/SgetOrSput.java
+++ b/src/main/java/com/android/tools/r8/code/SgetOrSput.java
@@ -5,6 +5,9 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 
 abstract class SgetOrSput extends Format21c<DexField> {
 
@@ -17,7 +20,11 @@
   }
 
   @Override
-  public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public final void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     getField().collectIndexedItems(indexedItems);
   }
 
diff --git a/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java b/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
index 90b88cc..b73779b 100644
--- a/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
+++ b/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
@@ -3,7 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.code;
 
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.ShortBuffer;
@@ -42,7 +45,12 @@
   }
 
   @Override
-  public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
+  public void write(
+      ShortBuffer dest,
+      ProgramMethod context,
+      GraphLens graphLens,
+      ObjectToOffsetMapping mapping,
+      LensCodeRewriterUtils rewriter) {
     writeFirst(2, dest);  // Pseudo-opcode = 0x0200
     write16BitValue(size, dest);
     for (int i = 0; i < size; i++) {
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 21b5cd4..0f23f43 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -69,7 +69,6 @@
 
 public class ApplicationWriter {
 
-  public final DexApplication application;
   public final AppView<?> appView;
   public final GraphLens graphLens;
   public final InitClassLens initClassLens;
@@ -146,18 +145,14 @@
   }
 
   public ApplicationWriter(
-      DexApplication application,
       AppView<?> appView,
-      InternalOptions options,
       List<Marker> markers,
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
       ProguardMapSupplier proguardMapSupplier) {
     this(
-        application,
         appView,
-        options,
         markers,
         graphLens,
         initClassLens,
@@ -167,20 +162,15 @@
   }
 
   public ApplicationWriter(
-      DexApplication application,
       AppView<?> appView,
-      InternalOptions options,
       List<Marker> markers,
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
       ProguardMapSupplier proguardMapSupplier,
       DexIndexedConsumer consumer) {
-    assert application != null;
-    this.application = application;
     this.appView = appView;
-    assert options != null;
-    this.options = options;
+    this.options = appView.options();
     this.desugaredLibraryCodeToKeep = CodeToKeep.createCodeToKeep(options, namingLens);
     this.markers = markers;
     this.graphLens = graphLens;
@@ -199,7 +189,7 @@
           options.getDexFilePerClassFileConsumer().combineSyntheticClassesWithPrimaryClass());
     } else if (!options.canUseMultidex()
         && options.mainDexKeepRules.isEmpty()
-        && application.mainDexList.isEmpty()
+        && appView.appInfo().app().mainDexList.isEmpty()
         && options.enableMainDexListCheck) {
       distributor = new VirtualFile.MonoDexDistributor(this, options);
     } else {
@@ -215,7 +205,7 @@
    * This needs to be done after distribute but before dex string sorting.
    */
   private void encodeChecksums(Iterable<VirtualFile> files) {
-    List<DexProgramClass> classes = application.classes();
+    Collection<DexProgramClass> classes = appView.appInfo().classes();
     Reference2LongMap<DexString> inputChecksums = new Reference2LongOpenHashMap<>(classes.size());
     for (DexProgramClass clazz : classes) {
       inputChecksums.put(clazz.getType().descriptor, clazz.getChecksum());
@@ -226,12 +216,12 @@
         DexString desc = clazz.type.descriptor;
         toWrite.addChecksum(desc.toString(), inputChecksums.getLong(desc));
       }
-      file.injectString(application.dexItemFactory.createString(toWrite.toJsonString()));
+      file.injectString(appView.dexItemFactory().createString(toWrite.toJsonString()));
     }
   }
 
   public void write(ExecutorService executorService) throws IOException, ExecutionException {
-    application.timing.begin("DexApplication.write");
+    appView.appInfo().app().timing.begin("DexApplication.write");
     ProguardMapId proguardMapId = null;
     if (proguardMapSupplier != null && options.proguardMapConsumer != null) {
       proguardMapId = proguardMapSupplier.writeProguardMap();
@@ -246,7 +236,7 @@
       }
       markerStrings = new ArrayList<>(markers.size());
       for (Marker marker : markers) {
-        markerStrings.add(application.dexItemFactory.createString(marker.toString()));
+        markerStrings.add(appView.dexItemFactory().createString(marker.toString()));
       }
     }
     try {
@@ -266,16 +256,14 @@
       }
       assert markers == null
           || markers.isEmpty()
-          || application.dexItemFactory.extractMarkers() != null;
-      assert appView == null
-          || appView.withProtoShrinker(
-              shrinker ->
-                  virtualFiles.stream().allMatch(shrinker::verifyDeadProtoTypesNotReferenced),
-              true);
+          || appView.dexItemFactory().extractMarkers() != null;
+      assert appView.withProtoShrinker(
+          shrinker -> virtualFiles.stream().allMatch(shrinker::verifyDeadProtoTypesNotReferenced),
+          true);
 
       // TODO(b/151313617): Sorting annotations mutates elements so run single threaded on main.
       SortAnnotations sortAnnotations = new SortAnnotations(namingLens);
-      application.classes().forEach((clazz) -> clazz.addDependencies(sortAnnotations));
+      appView.appInfo().classes().forEach((clazz) -> clazz.addDependencies(sortAnnotations));
 
       for (VirtualFile virtualFile : virtualFiles) {
         if (virtualFile.isEmpty()) {
@@ -305,10 +293,11 @@
                     }
                   }
                   ObjectToOffsetMapping objectMapping =
-                      virtualFile.computeMapping(application, namingLens, initClassLens);
+                      virtualFile.computeMapping(
+                          appView.appInfo(), graphLens, namingLens, initClassLens);
                   MethodToCodeObjectMapping codeMapping =
                       rewriteCodeWithJumboStrings(
-                          objectMapping, virtualFile.classes(), application);
+                          objectMapping, virtualFile.classes(), appView.appInfo().app());
                   ByteBufferResult result =
                       writeDexFile(objectMapping, codeMapping, byteBufferProvider);
                   ByteDataView data =
@@ -345,9 +334,9 @@
       // Fail if there are pending errors, e.g., the program consumers may have reported errors.
       options.reporter.failIfPendingErrors();
       // Supply info to all additional resource consumers.
-      supplyAdditionalConsumers(application, appView, graphLens, namingLens, options);
+      supplyAdditionalConsumers(appView.appInfo().app(), appView, graphLens, namingLens, options);
     } finally {
-      application.timing.end();
+      appView.appInfo().app().timing.end();
     }
   }
 
@@ -461,7 +450,7 @@
 
   private void insertAttributeAnnotations() {
     // Convert inner-class attributes to DEX annotations
-    for (DexProgramClass clazz : application.classes()) {
+    for (DexProgramClass clazz : appView.appInfo().classes()) {
       EnclosingMethodAttribute enclosingMethod = clazz.getEnclosingMethodAttribute();
       List<InnerClassAttribute> innerClasses = clazz.getInnerClasses();
       if (enclosingMethod == null && innerClasses.isEmpty()) {
@@ -609,7 +598,7 @@
             provider,
             objectMapping,
             codeMapping,
-            application,
+            appView.appInfo().app(),
             options,
             namingLens,
             desugaredLibraryCodeToKeep);
diff --git a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
index 037d769..b193e73 100644
--- a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
+++ b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
@@ -6,9 +6,11 @@
 import com.android.tools.r8.ByteBufferProvider;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.utils.EncodedValueUtils;
 import com.android.tools.r8.utils.LebUtils;
 import com.google.common.annotations.VisibleForTesting;
@@ -93,16 +95,20 @@
   }
 
   public void putInstructions(
-      Instruction[] insns, ObjectToOffsetMapping mapping, CodeToKeep desugaredLibraryCodeToKeep) {
+      DexCode code,
+      ProgramMethod context,
+      ObjectToOffsetMapping mapping,
+      CodeToKeep desugaredLibraryCodeToKeep) {
     int size = 0;
-    for (Instruction insn : insns) {
-      size += insn.getSize();
+    Instruction[] instructions = code.instructions;
+    for (Instruction instruction : instructions) {
+      size += instruction.getSize();
     }
     ensureSpaceFor(size * Short.BYTES);
     assert byteBuffer.position() % 2 == 0;
     ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
-    for (int i = 0; i < insns.length; i++) {
-      Instruction insn = insns[i];
+    for (int i = 0; i < instructions.length; i++) {
+      Instruction insn = instructions[i];
       DexMethod method = insn.getMethod();
       DexField field = insn.getField();
       if (field != null) {
@@ -117,7 +123,8 @@
       } else if (insn.isCheckCast()) {
         desugaredLibraryCodeToKeep.recordClass(insn.asCheckCast().getType());
       }
-      insn.write(shortBuffer, mapping);
+      insn.write(
+          shortBuffer, context, mapping.getGraphLens(), mapping, mapping.getLensCodeRewriter());
     }
     byteBuffer.position(byteBuffer.position() + shortBuffer.position() * Short.BYTES);
   }
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 da90a09..393297a 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -46,6 +46,8 @@
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
 import com.android.tools.r8.graph.ProgramClassVisitor;
+import com.android.tools.r8.graph.ProgramDexCode;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
@@ -175,7 +177,7 @@
     assert codeMapping.verifyCodeObjects(mixedSectionOffsets.getCodes());
 
     // Sort the codes first, as their order might impact size due to alignment constraints.
-    List<DexCode> codes = sortDexCodesByClassName();
+    List<ProgramDexCode> codes = sortDexCodesByClassName();
 
     // Output the debug_info_items first, as they have no dependencies.
     dest.moveTo(layout.getCodesOffset() + sizeOfCodeItems(codes));
@@ -185,8 +187,8 @@
       // Ensure deterministic ordering of debug info by sorting consistent with the code objects.
       layout.setDebugInfosOffset(dest.align(1));
       Set<DexDebugInfo> seen = new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
-      for (DexCode code : codes) {
-        DexDebugInfoForWriting info = code.getDebugInfoForWriting();
+      for (ProgramDexCode code : codes) {
+        DexDebugInfoForWriting info = code.getCode().getDebugInfoForWriting();
         if (info != null && seen.add(info)) {
           writeDebugItem(info);
         }
@@ -323,18 +325,19 @@
     return true;
   }
 
-  private List<DexCode> sortDexCodesByClassName() {
-    Map<DexCode, String> codeToSignatureMap = new IdentityHashMap<>();
-    List<DexCode> codesSorted = new ArrayList<>();
+  private List<ProgramDexCode> sortDexCodesByClassName() {
+    Map<ProgramDexCode, String> codeToSignatureMap = new IdentityHashMap<>();
+    List<ProgramDexCode> codesSorted = new ArrayList<>();
     for (DexProgramClass clazz : mapping.getClasses()) {
-      clazz.forEachMethod(
+      clazz.forEachProgramMethod(
           method -> {
-            DexCode code = codeMapping.getCode(method);
-            assert code != null || method.shouldNotHaveCode();
+            DexCode code = codeMapping.getCode(method.getDefinition());
+            assert code != null || method.getDefinition().shouldNotHaveCode();
             if (code != null) {
-              codesSorted.add(code);
-              addSignaturesFromMethod(
-                  method, code, codeToSignatureMap, application.getProguardMap());
+              ProgramDexCode programCode = new ProgramDexCode(code, method);
+              codesSorted.add(programCode);
+              codeToSignatureMap.put(
+                  programCode, getKeyForDexCodeSorting(method, application.getProguardMap()));
             }
           });
     }
@@ -342,21 +345,17 @@
     return codesSorted;
   }
 
-  private static void addSignaturesFromMethod(
-      DexEncodedMethod method,
-      DexCode code,
-      Map<DexCode, String> codeToSignatureMap,
-      ClassNameMapper proguardMap) {
+  private static String getKeyForDexCodeSorting(ProgramMethod method, ClassNameMapper proguardMap) {
     Signature signature;
     String originalClassName;
     if (proguardMap != null) {
-      signature = proguardMap.originalSignatureOf(method.method);
-      originalClassName = proguardMap.originalNameOf(method.holder());
+      signature = proguardMap.originalSignatureOf(method.getReference());
+      originalClassName = proguardMap.originalNameOf(method.getHolderType());
     } else {
-      signature = MethodSignature.fromDexMethod(method.method);
-      originalClassName = method.holder().toSourceString();
+      signature = MethodSignature.fromDexMethod(method.getReference());
+      originalClassName = method.getHolderType().toSourceString();
     }
-    codeToSignatureMap.put(code, originalClassName + signature);
+    return originalClassName + signature;
   }
 
   private <T extends IndexedDexItem> void writeFixedSectionItems(
@@ -380,8 +379,8 @@
     writeItems(items, offsetSetter, writer, 1);
   }
 
-  private <T extends DexItem> void writeItems(Collection<T> items, Consumer<Integer> offsetSetter,
-      Consumer<T> writer, int alignment) {
+  private <T> void writeItems(
+      Collection<T> items, Consumer<Integer> offsetSetter, Consumer<T> writer, int alignment) {
     if (items.isEmpty()) {
       offsetSetter.accept(0);
     } else {
@@ -390,11 +389,11 @@
     }
   }
 
-  private int sizeOfCodeItems(Iterable<DexCode> codes) {
+  private int sizeOfCodeItems(Iterable<ProgramDexCode> codes) {
     int size = 0;
-    for (DexCode code : codes) {
+    for (ProgramDexCode code : codes) {
       size = alignSize(4, size);
-      size += sizeOfCodeItem(code);
+      size += sizeOfCodeItem(code.getCode());
     }
     return size;
   }
@@ -488,7 +487,11 @@
     dest.putBytes(new DebugBytecodeWriter(debugInfo, mapping).generate());
   }
 
-  private void writeCodeItem(DexCode code) {
+  private void writeCodeItem(ProgramDexCode code) {
+    writeCodeItem(code.getCode(), code.getMethod());
+  }
+
+  private void writeCodeItem(DexCode code, ProgramMethod method) {
     mixedSectionOffsets.setOffsetFor(code, dest.align(4));
     // Fixed size header information.
     dest.putShort((short) code.registerSize);
@@ -500,7 +503,7 @@
     int insnSizeOffset = dest.position();
     dest.forward(4);
     // Write instruction stream.
-    dest.putInstructions(code.instructions, mapping, desugaredLibraryCodeToKeep);
+    dest.putInstructions(code, method, mapping, desugaredLibraryCodeToKeep);
     // Compute size and do the backward/forward dance to write the size at the beginning.
     int insnSize = dest.position() - insnSizeOffset - 4;
     dest.rewind(insnSize + 4);
diff --git a/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java b/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
index 709eb9d..3a88e5d 100644
--- a/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
+++ b/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
@@ -6,7 +6,7 @@
 
 import com.android.tools.r8.dex.VirtualFile.VirtualFileCycler;
 import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
@@ -71,7 +71,7 @@
 
     public void updateNumbersOfIds() {
       // Use a temporary VirtualFile to evaluate the number of ids in the group.
-      VirtualFile virtualFile = new VirtualFile(0, graphLens, initClassLens, namingLens);
+      VirtualFile virtualFile = new VirtualFile(0, appView, graphLens, initClassLens, namingLens);
       // Note: sort not needed.
       for (DexProgramClass clazz : members) {
         virtualFile.addClass(clazz);
@@ -158,29 +158,30 @@
 
     }
 
-    private boolean isDependingOnMainDexClass(Set<DexProgramClass> mainDexDependents,
-        DexProgramClass dexProgramClass) {
-      if (dexProgramClass == null) {
+    private boolean isDependingOnMainDexClass(
+        Set<DexProgramClass> mainDexDependents, DexProgramClass clazz) {
+      if (clazz == null) {
         return false;
       }
 
       // Think: build on one Map<dexProgramClass, Boolean> and split in a second step.
-      if (mainDexIndependents.contains(dexProgramClass)) {
+      if (mainDexIndependents.contains(clazz)) {
         return false;
       }
-      if (mainDexDependents.contains(dexProgramClass)) {
+      if (mainDexDependents.contains(clazz)) {
         return true;
       }
-      if (mainDex.classes().contains(dexProgramClass)) {
+      if (mainDex.classes().contains(clazz)) {
         return true;
       }
       boolean isDependent = false;
-      if (isDependingOnMainDexClass(mainDexDependents,
-          app.programDefinitionFor(dexProgramClass.superType))) {
+      if (isDependingOnMainDexClass(
+          mainDexDependents, appView.programDefinitionFor(clazz.superType, clazz))) {
         isDependent = true;
       } else {
-        for (DexType interfaze : dexProgramClass.interfaces.values) {
-          if (isDependingOnMainDexClass(mainDexDependents, app.programDefinitionFor(interfaze))) {
+        for (DexType interfaze : clazz.interfaces.values) {
+          if (isDependingOnMainDexClass(
+              mainDexDependents, appView.programDefinitionFor(interfaze, clazz))) {
             isDependent = true;
             break;
           }
@@ -188,38 +189,37 @@
       }
 
       if (isDependent) {
-        mainDexDependents.add(dexProgramClass);
+        mainDexDependents.add(clazz);
       } else {
-        mainDexIndependents.add(dexProgramClass);
+        mainDexIndependents.add(clazz);
       }
       return isDependent;
     }
 
-
-    private boolean isDependingOnMainDexIndependents(DexProgramClass dexProgramClass) {
-      if (dexProgramClass == null) {
+    private boolean isDependingOnMainDexIndependents(DexProgramClass clazz) {
+      if (clazz == null) {
         return false;
       }
 
       // Think: build on one Map<dexProgramClass, Boolean> and split in a second step.
-      if (independentsFromMainDexIndependents.contains(dexProgramClass)) {
+      if (independentsFromMainDexIndependents.contains(clazz)) {
         return false;
       }
-      if (dependentsOfMainDexIndependents.contains(dexProgramClass)) {
+      if (dependentsOfMainDexIndependents.contains(clazz)) {
         return true;
       }
-      if (mainDex.classes().contains(dexProgramClass)) {
+      if (mainDex.classes().contains(clazz)) {
         return false;
       }
-      if (mainDexIndependents.contains(dexProgramClass)) {
+      if (mainDexIndependents.contains(clazz)) {
         return true;
       }
       boolean isDependent = false;
-      if (isDependingOnMainDexIndependents(app.programDefinitionFor(dexProgramClass.superType))) {
+      if (isDependingOnMainDexIndependents(appView.programDefinitionFor(clazz.superType, clazz))) {
         isDependent = true;
       } else {
-        for (DexType interfaze : dexProgramClass.interfaces.values) {
-          if (isDependingOnMainDexIndependents(app.programDefinitionFor(interfaze))) {
+        for (DexType interfaze : clazz.interfaces.values) {
+          if (isDependingOnMainDexIndependents(appView.programDefinitionFor(interfaze, clazz))) {
             isDependent = true;
             break;
           }
@@ -227,9 +227,9 @@
       }
 
       if (isDependent) {
-        dependentsOfMainDexIndependents.add(dexProgramClass);
+        dependentsOfMainDexIndependents.add(clazz);
       } else {
-        independentsFromMainDexIndependents.add(dexProgramClass);
+        independentsFromMainDexIndependents.add(clazz);
       }
       return isDependent;
     }
@@ -245,12 +245,12 @@
     private final Map<DexProgramClass, Collection<DexProgramClass>> directSubClasses;
     private final Set<DexProgramClass> classes;
 
-    DirectSubClassesInfo(DexApplication app, Set<DexProgramClass> classes) {
+    DirectSubClassesInfo(AppView<?> appView, Set<DexProgramClass> classes) {
       Map<DexProgramClass, Collection<DexProgramClass>> directSubClasses = new HashMap<>();
       for (DexProgramClass clazz : classes) {
-        addDirectSubClass(app, classes, directSubClasses, clazz.superType, clazz);
+        addDirectSubClass(appView, classes, directSubClasses, clazz.superType, clazz);
         for (DexType interfaze : clazz.interfaces.values) {
-          addDirectSubClass(app, classes, directSubClasses, interfaze, clazz);
+          addDirectSubClass(appView, classes, directSubClasses, interfaze, clazz);
         }
       }
 
@@ -263,12 +263,13 @@
       return directSubClasses.getOrDefault(clazz, Collections.emptyList());
     }
 
-    private static void addDirectSubClass(DexApplication app,
+    private static void addDirectSubClass(
+        AppView<?> appView,
         Set<DexProgramClass> classes,
         Map<DexProgramClass, Collection<DexProgramClass>> directSubClasses,
         DexType superType,
         DexProgramClass clazz) {
-      DexProgramClass zuper = app.programDefinitionFor(superType);
+      DexProgramClass zuper = appView.programDefinitionFor(superType, clazz);
       // Don't bother collecting subclasses info that we won't use.
       if (zuper != null && classes.contains(zuper)) {
         Collection<DexProgramClass> subClasses =
@@ -283,7 +284,7 @@
   private final List<VirtualFile> dexes;
   private final BitSet fullDex = new BitSet();
   private final Set<DexProgramClass> classes;
-  private final DexApplication app;
+  private final AppView<?> appView;
   private int dexIndexOffset;
   private final GraphLens graphLens;
   private final InitClassLens initClassLens;
@@ -298,7 +299,7 @@
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
-      DexApplication app,
+      AppView<?> appView,
       ExecutorService executorService) {
     this.mainDex = mainDex;
     this.dexes = dexes;
@@ -307,10 +308,10 @@
     this.graphLens = graphLens;
     this.initClassLens = initClassLens;
     this.namingLens = namingLens;
-    this.app = app;
+    this.appView = appView;
     this.executorService = executorService;
 
-    directSubClasses = new DirectSubClassesInfo(app, classes);
+    directSubClasses = new DirectSubClassesInfo(appView, classes);
   }
 
   public void distribute() {
@@ -378,7 +379,7 @@
 
   private Collection<VirtualFile> assignGroup(ClassGroup group, List<VirtualFile> dexBlackList) {
     VirtualFileCycler cycler =
-        new VirtualFileCycler(dexes, graphLens, initClassLens, namingLens, dexIndexOffset);
+        new VirtualFileCycler(dexes, appView, graphLens, initClassLens, namingLens, dexIndexOffset);
     if (group.members.isEmpty()) {
       return Collections.emptyList();
     } else if (group.canFitInOneDex()) {
@@ -427,7 +428,7 @@
 
     Collection<VirtualFile> usedDex = new ArrayList<>();
     VirtualFileCycler cycler =
-        new VirtualFileCycler(dexes, graphLens, initClassLens, namingLens, dexIndexOffset);
+        new VirtualFileCycler(dexes, appView, graphLens, initClassLens, namingLens, dexIndexOffset);
     // Don't modify input dexBlackList. Think about modifying the input collection considering this
     // is private API.
     Set<VirtualFile> currentBlackList = new HashSet<>(dexBlackList);
@@ -581,9 +582,9 @@
     group.members.add(clazz);
 
     // Check dependencies are added to the group.
-    collectGroup(classes, group, app.programDefinitionFor(clazz.superType));
+    collectGroup(classes, group, appView.programDefinitionFor(clazz.superType, clazz));
     for (DexType interfaze : clazz.interfaces.values) {
-      collectGroup(classes, group, app.programDefinitionFor(interfaze));
+      collectGroup(classes, group, appView.programDefinitionFor(interfaze, clazz));
     }
 
     // Check that dependants are added to the group.
@@ -666,11 +667,11 @@
 
   private boolean hasDirectInheritanceInCollection(DexProgramClass clazz,
       Set<DexProgramClass> collection) {
-    if (collection.contains(app.programDefinitionFor(clazz.superType))) {
+    if (collection.contains(appView.programDefinitionFor(clazz.superType, clazz))) {
       return true;
     }
     for (DexType interfaze : clazz.interfaces.values) {
-      if (collection.contains(app.programDefinitionFor(interfaze))) {
+      if (collection.contains(appView.programDefinitionFor(interfaze, clazz))) {
         return true;
       }
     }
@@ -708,13 +709,13 @@
 
   private DexProgramClass findOneRootInSetFrom(DexProgramClass searchFrom,
       Set<DexProgramClass> classSet) {
-    DexProgramClass zuper = app.programDefinitionFor(searchFrom.superType);
+    DexProgramClass zuper = appView.programDefinitionFor(searchFrom.superType, searchFrom);
     if (classSet.contains(zuper)) {
       return findOneRootInSetFrom(zuper, classSet);
     }
     for (DexType interfaceType : searchFrom.interfaces.values) {
-      DexClass interfaceClass = app.definitionFor(interfaceType);
-      if (classSet.contains(interfaceClass)) {
+      DexClass interfaceClass = appView.definitionFor(interfaceType);
+      if (interfaceClass.isProgramClass() && classSet.contains(interfaceClass.asProgramClass())) {
         return findOneRootInSetFrom((DexProgramClass) interfaceClass, classSet);
       }
     }
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index b036d96..b08982f 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -6,7 +6,8 @@
 import com.android.tools.r8.FeatureSplit;
 import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
 import com.android.tools.r8.errors.InternalCompilerError;
-import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexField;
@@ -21,6 +22,7 @@
 import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.NamingLens;
@@ -77,30 +79,38 @@
 
   private final DexProgramClass primaryClass;
 
-  VirtualFile(int id, GraphLens graphLens, InitClassLens initClassLens, NamingLens namingLens) {
-    this(id, graphLens, initClassLens, namingLens, null, null);
+  VirtualFile(
+      int id,
+      AppView<?> appView,
+      GraphLens graphLens,
+      InitClassLens initClassLens,
+      NamingLens namingLens) {
+    this(id, appView, graphLens, initClassLens, namingLens, null, null);
   }
 
   VirtualFile(
       int id,
+      AppView<?> appView,
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
       FeatureSplit featureSplit) {
-    this(id, graphLens, initClassLens, namingLens, null, featureSplit);
+    this(id, appView, graphLens, initClassLens, namingLens, null, featureSplit);
   }
 
   private VirtualFile(
       int id,
+      AppView<?> appView,
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
       DexProgramClass primaryClass) {
-    this(id, graphLens, initClassLens, namingLens, primaryClass, null);
+    this(id, appView, graphLens, initClassLens, namingLens, primaryClass, null);
   }
 
   private VirtualFile(
       int id,
+      AppView<?> appView,
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
@@ -109,7 +119,7 @@
     this.id = id;
     this.indexedItems = new VirtualFileIndexedItemCollection(graphLens, initClassLens, namingLens);
     this.transaction =
-        new IndexedItemTransaction(indexedItems, graphLens, initClassLens, namingLens);
+        new IndexedItemTransaction(indexedItems, appView, graphLens, initClassLens, namingLens);
     this.primaryClass = primaryClass;
     this.featureSplit = featureSplit;
   }
@@ -193,10 +203,11 @@
   }
 
   public ObjectToOffsetMapping computeMapping(
-      DexApplication application, NamingLens namingLens, InitClassLens initClassLens) {
+      AppInfo appInfo, GraphLens graphLens, NamingLens namingLens, InitClassLens initClassLens) {
     assert transaction.isEmpty();
     return new ObjectToOffsetMapping(
-        application,
+        appInfo,
+        graphLens,
         namingLens,
         initClassLens,
         indexedItems.classes,
@@ -272,12 +283,12 @@
   }
 
   public abstract static class Distributor {
-    protected final DexApplication application;
+    protected final AppView<?> appView;
     protected final ApplicationWriter writer;
     protected final List<VirtualFile> virtualFiles = new ArrayList<>();
 
     Distributor(ApplicationWriter writer) {
-      this.application = writer.application;
+      this.appView = writer.appView;
       this.writer = writer;
     }
 
@@ -304,11 +315,12 @@
       HashMap<DexProgramClass, VirtualFile> files = new HashMap<>();
       Collection<DexProgramClass> synthetics = new ArrayList<>();
       // Assign dedicated virtual files for all program classes.
-      for (DexProgramClass clazz : application.classes()) {
+      for (DexProgramClass clazz : appView.appInfo().classes()) {
         if (!combineSyntheticClassesWithPrimaryClass || clazz.getSynthesizedFrom().isEmpty()) {
           VirtualFile file =
               new VirtualFile(
                   virtualFiles.size(),
+                  writer.appView,
                   writer.graphLens,
                   writer.initClassLens,
                   writer.namingLens,
@@ -345,13 +357,15 @@
       this.options = options;
 
       // Create the primary dex file. The distribution will add more if needed.
-      mainDexFile = new VirtualFile(0, writer.graphLens, writer.initClassLens, writer.namingLens);
+      mainDexFile =
+          new VirtualFile(
+              0, writer.appView, writer.graphLens, writer.initClassLens, writer.namingLens);
       assert virtualFiles.isEmpty();
       virtualFiles.add(mainDexFile);
       addMarkers(mainDexFile);
 
-      classes = Sets.newHashSet(application.classes());
-      originalNames = computeOriginalNameMapping(classes, application.getProguardMap());
+      classes = Sets.newHashSet(appView.appInfo().classes());
+      originalNames = computeOriginalNameMapping(classes, appView.appInfo().app().getProguardMap());
     }
 
     private void addMarkers(VirtualFile virtualFile) {
@@ -364,10 +378,11 @@
     }
 
     protected void fillForMainDexList(Set<DexProgramClass> classes) {
-      if (!application.mainDexList.isEmpty()) {
+      Set<DexType> mainDexList = appView.appInfo().app().mainDexList;
+      if (!mainDexList.isEmpty()) {
         VirtualFile mainDexFile = virtualFiles.get(0);
-        for (DexType type : application.mainDexList) {
-          DexClass clazz = application.definitionFor(type);
+        for (DexType type : mainDexList) {
+          DexClass clazz = appView.appInfo().definitionForWithoutExistenceAssert(type);
           if (clazz != null && clazz.isProgramClass()) {
             DexProgramClass programClass = (DexProgramClass) clazz;
             mainDexFile.addClass(programClass);
@@ -437,7 +452,7 @@
       // Pull out the classes that should go into feature splits.
       Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses =
           options.featureSplitConfiguration.getFeatureSplitClasses(
-              classes, application.getProguardMap());
+              classes, appView.appInfo().app().getProguardMap());
       if (featureSplitClasses.size() > 0) {
         for (Set<DexProgramClass> featureClasses : featureSplitClasses.values()) {
           classes.removeAll(featureClasses);
@@ -464,6 +479,7 @@
         VirtualFile featureFile =
             new VirtualFile(
                 0,
+                writer.appView,
                 writer.graphLens,
                 writer.initClassLens,
                 writer.namingLens,
@@ -476,9 +492,9 @@
 
         new PackageSplitPopulator(
                 filesForDistribution,
+                appView,
                 featureClasses,
                 originalNames,
-                application.dexItemFactory,
                 fillStrategy,
                 0,
                 writer.graphLens,
@@ -519,7 +535,8 @@
         assert virtualFiles.size() == 1;
         // The main dex file is filtered out, so ensure at least one file for the remaining classes.
         virtualFiles.add(
-            new VirtualFile(1, writer.graphLens, writer.initClassLens, writer.namingLens));
+            new VirtualFile(
+                1, writer.appView, writer.graphLens, writer.initClassLens, writer.namingLens));
         filesForDistribution = virtualFiles.subList(1, virtualFiles.size());
         fileIndexOffset = 1;
       }
@@ -536,7 +553,7 @@
                 writer.graphLens,
                 writer.initClassLens,
                 writer.namingLens,
-                writer.application,
+                writer.appView,
                 executorService)
             .distribute();
       } else {
@@ -545,9 +562,9 @@
         classes = sortClassesByPackage(classes, originalNames);
         new PackageSplitPopulator(
                 filesForDistribution,
+                appView,
                 classes,
                 originalNames,
-                application.dexItemFactory,
                 fillStrategy,
                 fileIndexOffset,
                 writer.graphLens,
@@ -695,6 +712,7 @@
     private final GraphLens graphLens;
     private final InitClassLens initClassLens;
     private final NamingLens namingLens;
+    private final LensCodeRewriterUtils rewriter;
 
     private final Set<DexProgramClass> classes = new LinkedHashSet<>();
     private final Set<DexField> fields = new LinkedHashSet<>();
@@ -707,6 +725,7 @@
 
     private IndexedItemTransaction(
         VirtualFileIndexedItemCollection base,
+        AppView<?> appView,
         GraphLens graphLens,
         InitClassLens initClassLens,
         NamingLens namingLens) {
@@ -714,6 +733,7 @@
       this.graphLens = graphLens;
       this.initClassLens = initClassLens;
       this.namingLens = namingLens;
+      this.rewriter = new LensCodeRewriterUtils(appView, graphLens);
     }
 
     private <T extends DexItem> boolean maybeInsert(T item, Set<T> set, Set<T> baseSet) {
@@ -725,7 +745,7 @@
     }
 
     void addClassAndDependencies(DexProgramClass clazz) {
-      clazz.collectIndexedItems(this);
+      clazz.collectIndexedItems(this, graphLens, rewriter);
     }
 
     @Override
@@ -855,6 +875,7 @@
   static class VirtualFileCycler {
 
     private final List<VirtualFile> files;
+    private final AppView<?> appView;
     private final GraphLens graphLens;
     private final InitClassLens initClassLens;
     private final NamingLens namingLens;
@@ -866,11 +887,13 @@
 
     VirtualFileCycler(
         List<VirtualFile> files,
+        AppView<?> appView,
         GraphLens graphLens,
         InitClassLens initClassLens,
         NamingLens namingLens,
         int fileIndexOffset) {
       this.files = files;
+      this.appView = appView;
       this.graphLens = graphLens;
       this.initClassLens = initClassLens;
       this.namingLens = namingLens;
@@ -904,7 +927,8 @@
         return activeFiles.next();
       } else {
         VirtualFile newFile =
-            new VirtualFile(nextFileId++, graphLens, initClassLens, namingLens, featuresplit);
+            new VirtualFile(
+                nextFileId++, appView, graphLens, initClassLens, namingLens, featuresplit);
         files.add(newFile);
         allFilesCyclic = Iterators.cycle(files);
         return newFile;
@@ -936,7 +960,8 @@
 
     VirtualFile addFile() {
       VirtualFile newFile =
-          new VirtualFile(nextFileId++, graphLens, initClassLens, namingLens, featuresplit);
+          new VirtualFile(
+              nextFileId++, appView, graphLens, initClassLens, namingLens, featuresplit);
       files.add(newFile);
 
       reset();
@@ -977,9 +1002,9 @@
 
     PackageSplitPopulator(
         List<VirtualFile> files,
+        AppView<?> appView,
         Set<DexProgramClass> classes,
         Map<DexProgramClass, String> originalNames,
-        DexItemFactory dexItemFactory,
         FillStrategy fillStrategy,
         int fileIndexOffset,
         GraphLens graphLens,
@@ -988,11 +1013,12 @@
         InternalOptions options) {
       this.classes = new ArrayList<>(classes);
       this.originalNames = originalNames;
-      this.dexItemFactory = dexItemFactory;
+      this.dexItemFactory = appView.dexItemFactory();
       this.fillStrategy = fillStrategy;
       this.options = options;
       this.cycler =
-          new VirtualFileCycler(files, graphLens, initClassLens, namingLens, fileIndexOffset);
+          new VirtualFileCycler(
+              files, appView, graphLens, initClassLens, namingLens, fileIndexOffset);
     }
 
     static boolean coveredByPrefix(String originalName, String currentPrefix) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexApplication.java b/src/main/java/com/android/tools/r8/graph/DexApplication.java
index d6d69a6..4b8de95 100644
--- a/src/main/java/com/android/tools/r8/graph/DexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DexApplication.java
@@ -57,6 +57,22 @@
 
   public abstract Builder<?> builder();
 
+  public DexDefinitionSupplier getDefinitionsSupplier(
+      SyntheticDefinitionsProvider syntheticDefinitionsProvider) {
+    DexApplication self = this;
+    return new DexDefinitionSupplier() {
+      @Override
+      public DexClass definitionFor(DexType type) {
+        return syntheticDefinitionsProvider.definitionFor(type, self::definitionFor);
+      }
+
+      @Override
+      public DexItemFactory dexItemFactory() {
+        return self.dexItemFactory;
+      }
+    };
+  }
+
   // Reorder classes randomly. Note that the order of classes in program or library
   // class collections should not matter for compilation of valid code and when running
   // with assertions enabled we reorder the classes randomly to catch possible issues.
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 6716297..8fb16b1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.conversion.DexSourceCode;
 import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
@@ -403,11 +404,15 @@
     return builder.toString();
   }
 
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems,
+      ProgramMethod context,
+      GraphLens graphLens,
+      LensCodeRewriterUtils rewriter) {
     highestSortingString = null;
     for (Instruction insn : instructions) {
       assert !insn.isDexItemBasedConstString();
-      insn.collectIndexedItems(indexedItems);
+      insn.collectIndexedItems(indexedItems, context, graphLens, rewriter);
       if (insn.isConstString()) {
         updateHighestSortingString(insn.asConstString().getString());
       } else if (insn.isConstStringJumbo()) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
index cc91bcd..9391a83 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
@@ -31,6 +31,10 @@
     return type == context.type ? context : contextIndependentDefinitionFor(type);
   }
 
+  default DexClass definitionFor(DexType type, ProgramMethod context) {
+    return definitionFor(type, context.getHolder());
+  }
+
   /**
    * Lookup for the program definition of a type from a given context.
    *
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 ce6934a..8e69541 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -30,7 +30,6 @@
 import com.android.tools.r8.code.NewInstance;
 import com.android.tools.r8.code.Throw;
 import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.dex.JumboStringRewriter;
 import com.android.tools.r8.dex.MethodToCodeObjectMapping;
 import com.android.tools.r8.dex.MixedSectionCollection;
@@ -648,20 +647,6 @@
     return "Encoded method " + method;
   }
 
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
-    checkIfObsolete();
-    this.method.collectIndexedItems(indexedItems);
-    if (code != null) {
-      if (code.isDexCode()) {
-        code.asDexCode().collectIndexedItems(indexedItems);
-      } else {
-        assert false;
-      }
-    }
-    annotations().collectIndexedItems(indexedItems);
-    parameterAnnotationsList.collectIndexedItems(indexedItems);
-  }
-
   @Override
   void collectMixedSectionItems(MixedSectionCollection mixedItems) {
     mixedItems.visit(this);
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 90c37ed..3e7bc63 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.dex.MixedSectionCollection;
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.origin.Origin;
@@ -233,7 +234,8 @@
     return originKind == Kind.CF;
   }
 
-  public void collectIndexedItems(IndexedItemCollection indexedItems) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems, GraphLens graphLens, LensCodeRewriterUtils rewriter) {
     if (indexedItems.addClass(this)) {
       type.collectIndexedItems(indexedItems);
       if (superType != null) {
@@ -255,7 +257,7 @@
         attribute.collectIndexedItems(indexedItems);
       }
       forEachField(field -> field.collectIndexedItems(indexedItems));
-      forEachMethod(method -> method.collectIndexedItems(indexedItems));
+      forEachProgramMethod(method -> method.collectIndexedItems(indexedItems, graphLens, rewriter));
     }
   }
 
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 fe85d28..c01aea0 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -74,22 +74,6 @@
     return classpathClasses;
   }
 
-  public DexDefinitionSupplier getDefinitionsSupplier(
-      SyntheticDefinitionsProvider syntheticDefinitionsProvider) {
-    DirectMappedDexApplication self = this;
-    return new DexDefinitionSupplier() {
-      @Override
-      public DexClass definitionFor(DexType type) {
-        return syntheticDefinitionsProvider.definitionFor(type, self::definitionFor);
-      }
-
-      @Override
-      public DexItemFactory dexItemFactory() {
-        return self.dexItemFactory;
-      }
-    };
-  }
-
   @Override
   public DexClass definitionFor(DexType type) {
     assert type.isClassType() : "Cannot lookup definition for type: " + type;
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
index 33f3b90..ecc7505 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.NamingLens;
 import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
 import it.unimi.dsi.fastutil.objects.Reference2IntMap;
@@ -23,8 +24,10 @@
   private final static int NOT_FOUND = -1;
   private final static int NOT_SET = -2;
 
+  private final GraphLens graphLens;
   private final NamingLens namingLens;
   private final InitClassLens initClassLens;
+  private final LensCodeRewriterUtils lensCodeRewriter;
 
   // Sorted collection of objects mapped to their offsets.
   private final DexProgramClass[] classes;
@@ -39,7 +42,8 @@
   private DexString firstJumboString;
 
   public ObjectToOffsetMapping(
-      DexApplication application,
+      AppInfo appInfo,
+      GraphLens graphLens,
       NamingLens namingLens,
       InitClassLens initClassLens,
       Collection<DexProgramClass> classes,
@@ -50,7 +54,7 @@
       Collection<DexString> strings,
       Collection<DexCallSite> callSites,
       Collection<DexMethodHandle> methodHandles) {
-    assert application != null;
+    assert appInfo != null;
     assert classes != null;
     assert protos != null;
     assert types != null;
@@ -60,9 +64,11 @@
     assert callSites != null;
     assert methodHandles != null;
     assert initClassLens != null;
+    this.graphLens = graphLens;
     this.namingLens = namingLens;
     this.initClassLens = initClassLens;
-    this.classes = sortClasses(application, classes, namingLens);
+    this.lensCodeRewriter = new LensCodeRewriterUtils(appInfo, graphLens);
+    this.classes = sortClasses(appInfo, classes, namingLens);
     this.protos = createSortedMap(protos, compare(namingLens), this::failOnOverflow);
     this.types = createSortedMap(types, compare(namingLens), this::failOnOverflow);
     this.methods = createSortedMap(methods, compare(namingLens), this::failOnOverflow);
@@ -114,11 +120,11 @@
 
     private final static int UNKNOWN_DEPTH = -1;
 
-    private final DexApplication application;
+    private final AppInfo appInfo;
     private final Reference2IntMap<DexProgramClass> depthOfClasses = new Reference2IntOpenHashMap<>();
 
-    ProgramClassDepthsMemoized(DexApplication application) {
-      this.application = application;
+    ProgramClassDepthsMemoized(AppInfo appInfo) {
+      this.appInfo = appInfo;
       depthOfClasses.defaultReturnValue(UNKNOWN_DEPTH);
     }
 
@@ -134,13 +140,13 @@
           maxDepth = 0;
         } else {
           maxDepth = 1;
-          DexProgramClass superClass = application.programDefinitionFor(superType);
+          DexProgramClass superClass = appInfo.programDefinitionFor(superType, programClass);
           if (superClass != null) {
             maxDepth = getDepth(superClass);
           }
         }
         for (DexType inf : programClass.interfaces.values) {
-          DexProgramClass infClass = application.programDefinitionFor(inf);
+          DexProgramClass infClass = appInfo.programDefinitionFor(inf, programClass);
           maxDepth = Math.max(maxDepth, infClass == null ? 1 : getDepth(infClass));
         }
         depth = maxDepth + 1;
@@ -152,9 +158,9 @@
   }
 
   private static DexProgramClass[] sortClasses(
-      DexApplication application, Collection<DexProgramClass> classes, NamingLens namingLens) {
+      AppInfo appInfo, Collection<DexProgramClass> classes, NamingLens namingLens) {
     // Collect classes in subtyping order, based on a sorted list of classes to start with.
-    ProgramClassDepthsMemoized classDepths = new ProgramClassDepthsMemoized(application);
+    ProgramClassDepthsMemoized classDepths = new ProgramClassDepthsMemoized(appInfo);
     List<DexProgramClass> sortedClasses =
         classes.stream()
             .sorted(
@@ -172,10 +178,18 @@
     return map == null ? Collections.emptyList() : map.keySet();
   }
 
+  public GraphLens getGraphLens() {
+    return graphLens;
+  }
+
   public NamingLens getNamingLens() {
     return namingLens;
   }
 
+  public LensCodeRewriterUtils getLensCodeRewriter() {
+    return lensCodeRewriter;
+  }
+
   public Collection<DexMethod> getMethods() {
     return keysOrEmpty(methods);
   }
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramDexCode.java b/src/main/java/com/android/tools/r8/graph/ProgramDexCode.java
new file mode 100644
index 0000000..93e42d1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ProgramDexCode.java
@@ -0,0 +1,24 @@
+// 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;
+
+public class ProgramDexCode {
+
+  private final DexCode code;
+  private final ProgramMethod method;
+
+  public ProgramDexCode(DexCode code, ProgramMethod method) {
+    this.code = code;
+    this.method = method;
+  }
+
+  public DexCode getCode() {
+    return code;
+  }
+
+  public ProgramMethod getMethod() {
+    return method;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index e69ade7..a1fe5c7 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -3,9 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.graph;
 
+import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.NumberGenerator;
 import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.origin.Origin;
@@ -35,6 +37,20 @@
         context, this, appView, valueNumberGenerator, callerPosition, origin, methodProcessor);
   }
 
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems, GraphLens graphLens, LensCodeRewriterUtils rewriter) {
+    DexEncodedMethod definition = getDefinition();
+    assert !definition.isObsolete();
+    assert !definition.hasCode() || definition.getCode().isDexCode();
+    getReference().collectIndexedItems(indexedItems);
+    Code code = definition.getCode();
+    if (code != null && code.isDexCode()) {
+      code.asDexCode().collectIndexedItems(indexedItems, this, graphLens, rewriter);
+    }
+    definition.annotations().collectIndexedItems(indexedItems);
+    definition.parameterAnnotationsList.collectIndexedItems(indexedItems);
+  }
+
   public boolean isStructurallyEqualTo(ProgramMethod other) {
     return getDefinition() == other.getDefinition() && getHolder() == other.getHolder();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 51905bf..576a376 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.conversion;
 
-import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY;
 import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
 import static com.android.tools.r8.ir.code.Invoke.Type.STATIC;
 import static com.android.tools.r8.ir.code.Invoke.Type.VIRTUAL;
@@ -41,13 +40,7 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexMethodHandle;
-import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
-import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.GraphLens.GraphLensLookupResult;
 import com.android.tools.r8.graph.ProgramMethod;
@@ -55,7 +48,6 @@
 import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfo;
 import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
 import com.android.tools.r8.graph.RewrittenPrototypeDescription.RewrittenTypeInfo;
-import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
 import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
 import com.android.tools.r8.ir.analysis.type.DestructivePhiTypeUpdater;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -101,7 +93,6 @@
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiFunction;
 
 public class LensCodeRewriter {
@@ -109,11 +100,12 @@
   private final AppView<? extends AppInfoWithClassHierarchy> appView;
 
   private final EnumUnboxer enumUnboxer;
-  private final Map<DexProto, DexProto> protoFixupCache = new ConcurrentHashMap<>();
+  private final LensCodeRewriterUtils helper;
 
   LensCodeRewriter(AppView<? extends AppInfoWithClassHierarchy> appView, EnumUnboxer enumUnboxer) {
     this.appView = appView;
     this.enumUnboxer = enumUnboxer;
+    this.helper = new LensCodeRewriterUtils(appView);
   }
 
   private Value makeOutValue(Instruction insn, IRCode code) {
@@ -152,7 +144,7 @@
             {
               InvokeCustom invokeCustom = current.asInvokeCustom();
               DexCallSite callSite = invokeCustom.getCallSite();
-              DexCallSite newCallSite = rewriteCallSite(callSite, method);
+              DexCallSite newCallSite = helper.rewriteCallSite(callSite, method);
               if (newCallSite != callSite) {
                 Value newOutValue = makeOutValue(invokeCustom, code);
                 InvokeCustom newInvokeCustom =
@@ -169,7 +161,7 @@
             {
               DexMethodHandle handle = current.asConstMethodHandle().getValue();
               DexMethodHandle newHandle =
-                  rewriteDexMethodHandle(handle, method, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
+                  helper.rewriteDexMethodHandle(handle, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY, method);
               if (newHandle != handle) {
                 Value newOutValue = makeOutValue(current, code);
                 iterator.replaceCurrentInstruction(new ConstMethodHandle(newOutValue, newHandle));
@@ -632,28 +624,6 @@
     return TypeElement.getNull();
   }
 
-  public DexCallSite rewriteCallSite(DexCallSite callSite, ProgramMethod context) {
-    DexItemFactory dexItemFactory = appView.dexItemFactory();
-    DexProto newMethodProto =
-        dexItemFactory.applyClassMappingToProto(
-            callSite.methodProto, appView.graphLens()::lookupType, protoFixupCache);
-    DexMethodHandle newBootstrapMethod =
-        rewriteDexMethodHandle(
-            callSite.bootstrapMethod, context, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
-    boolean isLambdaMetaFactory =
-        dexItemFactory.isLambdaMetafactoryMethod(callSite.bootstrapMethod.asMethod());
-    MethodHandleUse methodHandleUse =
-        isLambdaMetaFactory ? ARGUMENT_TO_LAMBDA_METAFACTORY : NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
-    List<DexValue> newArgs = rewriteBootstrapArgs(callSite.bootstrapArgs, context, methodHandleUse);
-    if (!newMethodProto.equals(callSite.methodProto)
-        || newBootstrapMethod != callSite.bootstrapMethod
-        || !newArgs.equals(callSite.bootstrapArgs)) {
-      return dexItemFactory.createCallSite(
-          callSite.methodName, newMethodProto, newBootstrapMethod, newArgs);
-    }
-    return callSite;
-  }
-
   // If the given invoke is on the form "invoke-direct A.<init>, v0, ..." and the definition of
   // value v0 is "new-instance v0, B", where B is a subtype of A (see the Art800 and B116282409
   // tests), then fail with a compilation error if A has previously been merged into B.
@@ -731,116 +701,6 @@
     return !deadCatchHandlers.isEmpty();
   }
 
-  private List<DexValue> rewriteBootstrapArgs(
-      List<DexValue> bootstrapArgs, ProgramMethod method, MethodHandleUse use) {
-    List<DexValue> newBootstrapArgs = null;
-    boolean changed = false;
-    for (int i = 0; i < bootstrapArgs.size(); i++) {
-      DexValue argument = bootstrapArgs.get(i);
-      DexValue newArgument = null;
-      switch (argument.getValueKind()) {
-        case METHOD_HANDLE:
-          newArgument = rewriteDexValueMethodHandle(argument.asDexValueMethodHandle(), method, use);
-          break;
-        case METHOD_TYPE:
-          newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
-          break;
-        case TYPE:
-          DexType oldType = argument.asDexValueType().value;
-          DexType newType = appView.graphLens().lookupType(oldType);
-          if (newType != oldType) {
-            newArgument = new DexValueType(newType);
-          }
-          break;
-        default:
-          // Intentionally empty.
-      }
-      if (newArgument != null) {
-        if (newBootstrapArgs == null) {
-          newBootstrapArgs = new ArrayList<>(bootstrapArgs.subList(0, i));
-        }
-        newBootstrapArgs.add(newArgument);
-        changed = true;
-      } else if (newBootstrapArgs != null) {
-        newBootstrapArgs.add(argument);
-      }
-    }
-    return changed ? newBootstrapArgs : bootstrapArgs;
-  }
-
-  private DexValueMethodHandle rewriteDexValueMethodHandle(
-      DexValueMethodHandle methodHandle, ProgramMethod context, MethodHandleUse use) {
-    DexMethodHandle oldHandle = methodHandle.value;
-    DexMethodHandle newHandle = rewriteDexMethodHandle(oldHandle, context, use);
-    return newHandle != oldHandle ? new DexValueMethodHandle(newHandle) : methodHandle;
-  }
-
-  private DexMethodHandle rewriteDexMethodHandle(
-      DexMethodHandle methodHandle, ProgramMethod context, MethodHandleUse use) {
-    if (methodHandle.isMethodHandle()) {
-      DexMethod invokedMethod = methodHandle.asMethod();
-      MethodHandleType oldType = methodHandle.type;
-      GraphLensLookupResult lensLookup =
-          appView
-              .graphLens()
-              .lookupMethod(invokedMethod, context.getReference(), oldType.toInvokeType());
-      DexMethod rewrittenTarget = lensLookup.getMethod();
-      DexMethod actualTarget;
-      MethodHandleType newType;
-      if (use == ARGUMENT_TO_LAMBDA_METAFACTORY) {
-        // Lambda metafactory arguments will be lambda desugared away and therefore cannot flow
-        // to a MethodHandle.invokeExact call. We can therefore member-rebind with no issues.
-        actualTarget = rewrittenTarget;
-        newType = lensLookup.getType().toMethodHandle(actualTarget);
-      } else {
-        assert use == NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
-        // MethodHandles that are not arguments to a lambda metafactory will not be desugared
-        // away. Therefore they could flow to a MethodHandle.invokeExact call which means that
-        // we cannot member rebind. We therefore keep the receiver and also pin the receiver
-        // with a keep rule (see Enqueuer.registerMethodHandle).
-        actualTarget =
-            appView
-                .dexItemFactory()
-                .createMethod(invokedMethod.holder, rewrittenTarget.proto, rewrittenTarget.name);
-        newType = oldType;
-        if (oldType.isInvokeDirect()) {
-          // For an invoke direct, the rewritten target must have the same holder as the original.
-          // If the method has changed from private to public we need to use virtual instead of
-          // direct.
-          assert rewrittenTarget.holder == actualTarget.holder;
-          newType = lensLookup.getType().toMethodHandle(actualTarget);
-          assert newType == MethodHandleType.INVOKE_DIRECT
-              || newType == MethodHandleType.INVOKE_INSTANCE;
-        }
-      }
-      if (newType != oldType || actualTarget != invokedMethod || rewrittenTarget != actualTarget) {
-        DexClass holder = appView.definitionFor(actualTarget.holder);
-        boolean isInterface = holder != null ? holder.isInterface() : methodHandle.isInterface;
-        return new DexMethodHandle(
-            newType,
-            actualTarget,
-            isInterface,
-            rewrittenTarget != actualTarget ? rewrittenTarget : null);
-      }
-    } else {
-      DexField field = methodHandle.asField();
-      DexField actualField = appView.graphLens().lookupField(field);
-      if (actualField != field) {
-        return new DexMethodHandle(methodHandle.type, actualField, methodHandle.isInterface);
-      }
-    }
-    return methodHandle;
-  }
-
-  private DexValueMethodType rewriteDexMethodType(DexValueMethodType type) {
-    DexProto oldProto = type.value;
-    DexProto newProto =
-        appView
-            .dexItemFactory()
-            .applyClassMappingToProto(oldProto, appView.graphLens()::lookupType, protoFixupCache);
-    return newProto != oldProto ? new DexValueMethodType(newProto) : type;
-  }
-
   class InstructionReplacer {
 
     private final IRCode code;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java
new file mode 100644
index 0000000..27b3064
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java
@@ -0,0 +1,180 @@
+// 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.conversion;
+
+import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY;
+import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexCallSite;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexMethodHandle;
+import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
+import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
+import com.android.tools.r8.graph.DexValue.DexValueMethodType;
+import com.android.tools.r8.graph.DexValue.DexValueType;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.GraphLens.GraphLensLookupResult;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class LensCodeRewriterUtils {
+
+  private final DexDefinitionSupplier definitions;
+  private final GraphLens graphLens;
+
+  private final Map<DexProto, DexProto> protoFixupCache = new ConcurrentHashMap<>();
+
+  public LensCodeRewriterUtils(AppView<?> appView) {
+    this(appView, appView.graphLens());
+  }
+
+  public LensCodeRewriterUtils(DexDefinitionSupplier definitions, GraphLens graphLens) {
+    this.definitions = definitions;
+    this.graphLens = graphLens;
+  }
+
+  public DexCallSite rewriteCallSite(DexCallSite callSite, ProgramMethod context) {
+    DexItemFactory dexItemFactory = definitions.dexItemFactory();
+    DexProto newMethodProto = rewriteProto(callSite.methodProto);
+    DexMethodHandle newBootstrapMethod =
+        rewriteDexMethodHandle(
+            callSite.bootstrapMethod, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY, context);
+    boolean isLambdaMetaFactory =
+        dexItemFactory.isLambdaMetafactoryMethod(callSite.bootstrapMethod.asMethod());
+    MethodHandleUse methodHandleUse =
+        isLambdaMetaFactory ? ARGUMENT_TO_LAMBDA_METAFACTORY : NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+    List<DexValue> newArgs =
+        rewriteBootstrapArguments(callSite.bootstrapArgs, methodHandleUse, context);
+    if (!newMethodProto.equals(callSite.methodProto)
+        || newBootstrapMethod != callSite.bootstrapMethod
+        || !newArgs.equals(callSite.bootstrapArgs)) {
+      return dexItemFactory.createCallSite(
+          callSite.methodName, newMethodProto, newBootstrapMethod, newArgs);
+    }
+    return callSite;
+  }
+
+  public DexMethodHandle rewriteDexMethodHandle(
+      DexMethodHandle methodHandle, MethodHandleUse use, ProgramMethod context) {
+    if (methodHandle.isMethodHandle()) {
+      DexMethod invokedMethod = methodHandle.asMethod();
+      MethodHandleType oldType = methodHandle.type;
+      GraphLensLookupResult lensLookup =
+          graphLens.lookupMethod(invokedMethod, context.getReference(), oldType.toInvokeType());
+      DexMethod rewrittenTarget = lensLookup.getMethod();
+      DexMethod actualTarget;
+      MethodHandleType newType;
+      if (use == ARGUMENT_TO_LAMBDA_METAFACTORY) {
+        // Lambda metafactory arguments will be lambda desugared away and therefore cannot flow
+        // to a MethodHandle.invokeExact call. We can therefore member-rebind with no issues.
+        actualTarget = rewrittenTarget;
+        newType = lensLookup.getType().toMethodHandle(actualTarget);
+      } else {
+        assert use == NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+        // MethodHandles that are not arguments to a lambda metafactory will not be desugared
+        // away. Therefore they could flow to a MethodHandle.invokeExact call which means that
+        // we cannot member rebind. We therefore keep the receiver and also pin the receiver
+        // with a keep rule (see Enqueuer.registerMethodHandle).
+        actualTarget =
+            definitions
+                .dexItemFactory()
+                .createMethod(invokedMethod.holder, rewrittenTarget.proto, rewrittenTarget.name);
+        newType = oldType;
+        if (oldType.isInvokeDirect()) {
+          // For an invoke direct, the rewritten target must have the same holder as the original.
+          // If the method has changed from private to public we need to use virtual instead of
+          // direct.
+          assert rewrittenTarget.holder == actualTarget.holder;
+          newType = lensLookup.getType().toMethodHandle(actualTarget);
+          assert newType == MethodHandleType.INVOKE_DIRECT
+              || newType == MethodHandleType.INVOKE_INSTANCE;
+        }
+      }
+      if (newType != oldType || actualTarget != invokedMethod || rewrittenTarget != actualTarget) {
+        DexClass holder = definitions.definitionFor(actualTarget.holder, context);
+        boolean isInterface = holder != null ? holder.isInterface() : methodHandle.isInterface;
+        return new DexMethodHandle(
+            newType,
+            actualTarget,
+            isInterface,
+            rewrittenTarget != actualTarget ? rewrittenTarget : null);
+      }
+    } else {
+      DexField field = methodHandle.asField();
+      DexField actualField = graphLens.lookupField(field);
+      if (actualField != field) {
+        return new DexMethodHandle(methodHandle.type, actualField, methodHandle.isInterface);
+      }
+    }
+    return methodHandle;
+  }
+
+  private List<DexValue> rewriteBootstrapArguments(
+      List<DexValue> bootstrapArgs, MethodHandleUse use, ProgramMethod context) {
+    List<DexValue> newBootstrapArgs = null;
+    boolean changed = false;
+    for (int i = 0; i < bootstrapArgs.size(); i++) {
+      DexValue argument = bootstrapArgs.get(i);
+      DexValue newArgument = rewriteBootstrapArgument(argument, use, context);
+      if (newArgument != argument) {
+        if (newBootstrapArgs == null) {
+          newBootstrapArgs = new ArrayList<>(bootstrapArgs.subList(0, i));
+        }
+        newBootstrapArgs.add(newArgument);
+        changed = true;
+      } else if (newBootstrapArgs != null) {
+        newBootstrapArgs.add(newArgument);
+      }
+    }
+    return changed ? newBootstrapArgs : bootstrapArgs;
+  }
+
+  private DexValueMethodType rewriteDexMethodType(DexValueMethodType type) {
+    DexProto oldProto = type.value;
+    DexProto newProto = rewriteProto(oldProto);
+    return newProto != oldProto ? new DexValueMethodType(newProto) : type;
+  }
+
+  private DexValue rewriteBootstrapArgument(
+      DexValue value, MethodHandleUse use, ProgramMethod context) {
+    switch (value.getValueKind()) {
+      case METHOD_HANDLE:
+        return rewriteDexValueMethodHandle(value.asDexValueMethodHandle(), use, context);
+      case METHOD_TYPE:
+        return rewriteDexMethodType(value.asDexValueMethodType());
+      case TYPE:
+        DexType oldType = value.asDexValueType().value;
+        DexType newType = graphLens.lookupType(oldType);
+        return newType != oldType ? new DexValueType(newType) : value;
+      default:
+        return value;
+    }
+  }
+
+  public DexProto rewriteProto(DexProto proto) {
+    return definitions
+        .dexItemFactory()
+        .applyClassMappingToProto(proto, graphLens::lookupType, protoFixupCache);
+  }
+
+  private DexValueMethodHandle rewriteDexValueMethodHandle(
+      DexValueMethodHandle methodHandle, MethodHandleUse use, ProgramMethod context) {
+    DexMethodHandle oldHandle = methodHandle.value;
+    DexMethodHandle newHandle = rewriteDexMethodHandle(oldHandle, use, context);
+    return newHandle != oldHandle ? new DexValueMethodHandle(newHandle) : methodHandle;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java b/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java
index eeedbab..b48e0a93 100644
--- a/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java
+++ b/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java
@@ -3,11 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.dex;
 
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexDebugEvent;
 import com.android.tools.r8.graph.DexDebugInfo;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.naming.NamingLens;
@@ -21,8 +23,10 @@
 
   private ObjectToOffsetMapping emptyObjectTObjectMapping() {
     return new ObjectToOffsetMapping(
-        DexApplication.builder(new InternalOptions(new DexItemFactory(), new Reporter()), null)
-            .build(),
+        AppInfo.createInitialAppInfo(
+            DexApplication.builder(new InternalOptions(new DexItemFactory(), new Reporter()), null)
+                .build()),
+        GraphLens.getIdentityLens(),
         NamingLens.getIdentityLens(),
         InitClassLens.getDefault(),
         Collections.emptyList(),
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index 5cb94de..4d3b4b7 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -153,9 +153,7 @@
     options.programConsumer = consumer;
     ApplicationWriter writer =
         new ApplicationWriter(
-            application,
             AppView.createForD8(AppInfo.createInitialAppInfo(application)),
-            options,
             null,
             GraphLens.getIdentityLens(),
             InitClassLens.getDefault(),
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 fdc2ab9..915e928 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -866,9 +866,7 @@
     DirectMappedDexApplication application = builder.build().toDirect();
     ApplicationWriter writer =
         new ApplicationWriter(
-            application,
             AppView.createForD8(AppInfo.createInitialAppInfo(application)),
-            options,
             null,
             GraphLens.getIdentityLens(),
             InitClassLens.getDefault(),
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java
index ac64695..693af00 100644
--- a/src/test/java/com/android/tools/r8/utils/Smali.java
+++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -115,9 +115,7 @@
       DexApplication dexApp = new ApplicationReader(app, options, Timing.empty()).read(executor);
       ApplicationWriter writer =
           new ApplicationWriter(
-              dexApp,
               AppView.createForD8(AppInfo.createInitialAppInfo(dexApp)),
-              options,
               null,
               GraphLens.getIdentityLens(),
               InitClassLens.getDefault(),