Merge commit '02f914d0156388824d5df2fece4be0d2ec36d01b' into dev-release
diff --git a/.gitignore b/.gitignore
index e1b9f6d..d76279a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -120,6 +120,8 @@
 third_party/kotlin/kotlin-compiler-1.5.0
 third_party/kotlin/kotlin-compiler-1.6.0.tar.gz
 third_party/kotlin/kotlin-compiler-1.6.0
+third_party/kotlin/kotlin-compiler-1.7.0.tar.gz
+third_party/kotlin/kotlin-compiler-1.7.0
 third_party/kotlin/kotlin-compiler-dev.tar.gz
 third_party/kotlin/kotlin-compiler-dev
 third_party/kotlinx-coroutines-1.3.6.tar.gz
diff --git a/build.gradle b/build.gradle
index 7c3a95c..5b9c8df 100644
--- a/build.gradle
+++ b/build.gradle
@@ -43,7 +43,7 @@
     // The kotlin version is only here to specify the kotlin language level,
     // all kotlin compilations are done in tests.
     kotlinVersion = '1.6.0'
-    kotlinExtMetadataJVMVersion = '0.4.1'
+    kotlinExtMetadataJVMVersion = '0.5.0'
     smaliVersion = '2.2b4'
     errorproneVersion = '2.3.2'
     testngVersion = '6.10'
@@ -346,6 +346,7 @@
                 "kotlin/kotlin-compiler-1.4.20",
                 "kotlin/kotlin-compiler-1.5.0",
                 "kotlin/kotlin-compiler-1.6.0",
+                "kotlin/kotlin-compiler-1.7.0",
                 "kotlinx-coroutines-1.3.6",
                 "openjdk/openjdk-rt-1.8",
                 "openjdk/desugar_jdk_libs",
@@ -1025,6 +1026,7 @@
     from sourceSets.test.output
     // We only want to include tests that use R8 when generating keep rules for applymapping.
     include "com/android/tools/r8/**"
+    include "android/**"
     include "dalvik/**"
 }
 
diff --git a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
index e612d68..293e189 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -79,6 +79,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.objectweb.asm.Opcodes;
 
 /** Rudimentary printer to print the source representation for creating CfCode object. */
 public class CfCodePrinter extends CfPrinter {
@@ -124,8 +125,8 @@
             .append(" ")
             .append(methodName)
             .append("(")
-            .append(r8Type("InternalOptions", "utils"))
-            .append(" options, ")
+            .append(dexItemFactoryType())
+            .append(" factory, ")
             .append(r8Type("DexMethod", "graph"))
             .append(" method) {");
 
@@ -267,7 +268,7 @@
   }
 
   private String dexString(DexString string) {
-    return "options.itemFactory.createString(" + quote(string.toString()) + ")";
+    return "factory.createString(" + quote(string.toString()) + ")";
   }
 
   private final Map<String, String> knownTypeFields =
@@ -303,17 +304,15 @@
     String descriptor = type.toDescriptorString();
     String field = knownTypeFields.get(descriptor);
     if (field != null) {
-      return "options.itemFactory." + field;
+      return "factory." + field;
     }
     synthesizedTypes.add(descriptor);
-    return "options.itemFactory.createType(" + quote(descriptor) + ")";
+    return "factory.createType(" + quote(descriptor) + ")";
   }
 
   private String dexProto(DexProto proto) {
     StringBuilder builder =
-        new StringBuilder()
-            .append("options.itemFactory.createProto(")
-            .append(dexType(proto.returnType));
+        new StringBuilder().append("factory.createProto(").append(dexType(proto.returnType));
     for (DexType param : proto.parameters.values) {
       builder.append(", ").append(dexType(param));
     }
@@ -321,7 +320,7 @@
   }
 
   private String dexMethod(DexMethod method) {
-    return "options.itemFactory.createMethod("
+    return "factory.createMethod("
         + dexType(method.holder)
         + ", "
         + dexProto(method.proto)
@@ -331,7 +330,7 @@
   }
 
   private String dexField(DexField field) {
-    return "options.itemFactory.createField("
+    return "factory.createField("
         + dexType(field.holder)
         + ", "
         + dexType(field.type)
@@ -593,7 +592,22 @@
 
   @Override
   public void print(CfFieldInstruction insn) {
-    throw new Unreachable();
+    switch (insn.getOpcode()) {
+      case Opcodes.GETFIELD:
+        printNewInstruction("CfInstanceFieldRead", dexField(insn.getField()));
+        break;
+      case Opcodes.PUTFIELD:
+        printNewInstruction("CfInstanceFieldWrite", dexField(insn.getField()));
+        break;
+      case Opcodes.GETSTATIC:
+        printNewInstruction("CfStaticFieldRead", dexField(insn.getField()));
+        break;
+      case Opcodes.PUTSTATIC:
+        printNewInstruction("CfStaticFieldWrite", dexField(insn.getField()));
+        break;
+      default:
+        throw new Unreachable();
+    }
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index 2640c16..2746906 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -134,7 +134,7 @@
       case Pop:
         {
           Slot pop = state.pop();
-          assert !pop.type.isWide();
+          assert !pop.type.isWide() : "Expected stack type to be single width";
           break;
         }
       case Pop2:
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 51a4a4a..ce22d5c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -573,11 +573,11 @@
   }
 
   public boolean belongsToDirectPool() {
-    return accessFlags.isStatic() || accessFlags.isPrivate() || accessFlags.isConstructor();
+    return accessFlags.belongsToDirectPool();
   }
 
   public boolean belongsToVirtualPool() {
-    return !belongsToDirectPool();
+    return accessFlags.belongsToVirtualPool();
   }
 
   @Override
@@ -1530,8 +1530,13 @@
       return this;
     }
 
+    public Builder setCode(Function<DexMethod, Code> fn) {
+      this.code = fn.apply(method);
+      return this;
+    }
+
     public Builder unsetCode() {
-      return setCode(null);
+      return setCode((Code) null);
     }
 
     public Builder setGenericSignature(MethodTypeSignature methodSignature) {
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
index a20ab1d..12da839 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
@@ -65,6 +65,14 @@
     return new Builder();
   }
 
+  public boolean belongsToDirectPool() {
+    return isStatic() || isPrivate() || isConstructor();
+  }
+
+  public boolean belongsToVirtualPool() {
+    return !belongsToDirectPool();
+  }
+
   @Override
   public MethodAccessFlags copy() {
     return new MethodAccessFlags(originalFlags, modifiedFlags);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
index e195eac..36f717a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
@@ -174,6 +174,9 @@
                 definition.markNotProcessed();
               }
               methodProcessor.processMethod(method, instructionDesugaringEventConsumer);
+              if (interfaceProcessor != null) {
+                interfaceProcessor.processMethod(method, instructionDesugaringEventConsumer);
+              }
             },
             executorService);
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
index 8236617..6137206 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
@@ -24,6 +24,7 @@
         ForwardMethodBuilder.builder(appView.dexItemFactory()).setStaticSource(accessor);
     switch (type) {
       case INVOKE_INSTANCE:
+      case INVOKE_INTERFACE:
         {
           forwardMethodBuilder.setVirtualTarget(target, isInterface);
           break;
@@ -43,8 +44,6 @@
           forwardMethodBuilder.setConstructorTarget(target, appView.dexItemFactory());
           break;
         }
-      case INVOKE_INTERFACE:
-        throw new Unreachable("Accessor for an interface method?");
       default:
         throw new Unreachable();
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 5011171..9a4e70c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -1078,8 +1078,8 @@
                 ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteMapOfEmpty())
                 : new MethodGenerator(
                     method,
-                    (options, methodArg) ->
-                        CollectionMethodGenerators.generateMapOf(options, methodArg, formalCount)));
+                    (ignore, methodArg) ->
+                        CollectionMethodGenerators.generateMapOf(factory, methodArg, formalCount)));
       }
       proto = factory.createProto(type, factory.createArrayType(1, factory.mapEntryType));
       method = factory.createMethod(type, proto, "ofEntries");
@@ -1696,15 +1696,17 @@
                       .disableAndroidApiLevelCheck()
                       .setProto(getProto(appView.dexItemFactory()))
                       .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
-                      .setCode(methodSig -> generateTemplateMethod(appView.options(), methodSig)));
+                      .setCode(
+                          methodSig ->
+                              generateTemplateMethod(appView.dexItemFactory(), methodSig)));
     }
 
     public DexProto getProto(DexItemFactory itemFactory) {
       return method.proto;
     }
 
-    public Code generateTemplateMethod(InternalOptions options, DexMethod method) {
-      return factory.create(options, method);
+    public Code generateTemplateMethod(DexItemFactory dexItemFactory, DexMethod method) {
+      return factory.create(dexItemFactory, method);
     }
   }
 
@@ -1743,7 +1745,7 @@
 
   private interface TemplateMethodFactory {
 
-    CfCode create(InternalOptions options, DexMethod method);
+    CfCode create(DexItemFactory factory, DexMethod method);
   }
 
   public interface MethodInvokeRewriter {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index fb51c23..46266fc 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -322,6 +322,8 @@
       case INVOKE_SUPER:
         throw new Unimplemented("Method references to super methods are not yet supported");
       case INVOKE_INTERFACE:
+        // TODO(b/238085938): Investigate if we can do something smart if
+        // canAccessModifyLambdaImplMethod().
         return createInterfaceMethodTarget(accessedFrom);
       case INVOKE_CONSTRUCTOR:
         return createConstructorTarget(accessedFrom);
@@ -423,19 +425,23 @@
     }
   }
 
+  // Create targets for interface methods.
+  private Target createInterfaceMethodTarget(ProgramMethod accessedFrom) {
+    assert descriptor.implHandle.type.isInvokeInterface();
+    return createInstanceOrInterfaceTarget(accessedFrom);
+  }
+
   // Create targets for instance method referenced directly without
   // lambda$ methods. It may require creation of accessors in some cases.
   private Target createInstanceMethodTarget(ProgramMethod accessedFrom) {
     assert descriptor.implHandle.type.isInvokeInstance() ||
         descriptor.implHandle.type.isInvokeDirect();
+    return createInstanceOrInterfaceTarget(accessedFrom);
+  }
 
+  private Target createInstanceOrInterfaceTarget(ProgramMethod accessedFrom) {
     if (doesNotNeedAccessor(accessedFrom)) {
-      return new NoAccessorMethodTarget(
-          descriptor.implHandle.asMethod(),
-          descriptor.implHandle.type.isInvokeDirect()
-              ? Type.DIRECT
-              : descriptor.implHandle.type.isInvokeStatic() ? Type.STATIC : Type.VIRTUAL,
-          descriptor.implHandle.isInterface);
+      return NoAccessorMethodTarget.create(descriptor);
     }
 
     // We need to generate an accessor method in `accessedFrom` class/interface
@@ -459,12 +465,8 @@
             .createMethod(
                 accessedFrom.getHolderType(), accessorProto, generateUniqueLambdaMethodName());
 
-    return new ClassMethodWithAccessorTarget(
-        descriptor.implHandle.asMethod(),
-        descriptor.implHandle.isInterface,
-        descriptor.implHandle.type,
-        accessorMethod,
-        appView);
+    return ClassMethodWithAccessorTarget.create(
+        descriptor.implHandle, accessedFrom, accessorMethod, appView);
   }
 
   // Create targets for static method referenced directly without
@@ -473,8 +475,7 @@
     assert descriptor.implHandle.type.isInvokeStatic();
 
     if (doesNotNeedAccessor(accessedFrom)) {
-      return new NoAccessorMethodTarget(
-          descriptor.implHandle.asMethod(), Type.STATIC, descriptor.implHandle.isInterface);
+      return NoAccessorMethodTarget.create(descriptor);
     }
 
     // We need to generate an accessor method in `accessedFrom` class/interface
@@ -487,12 +488,8 @@
                 accessedFrom.getHolderType(),
                 descriptor.implHandle.asMethod().proto,
                 generateUniqueLambdaMethodName());
-    return new ClassMethodWithAccessorTarget(
-        descriptor.implHandle.asMethod(),
-        descriptor.implHandle.isInterface,
-        descriptor.implHandle.type,
-        accessorMethod,
-        appView);
+    return ClassMethodWithAccessorTarget.create(
+        descriptor.implHandle, accessedFrom, accessorMethod, appView);
   }
 
   // Create targets for constructor referenced directly without lambda$ methods.
@@ -503,8 +500,7 @@
     assert implHandle.type.isInvokeConstructor();
 
     if (doesNotNeedAccessor(accessedFrom)) {
-      return new NoAccessorMethodTarget(
-          descriptor.implHandle.asMethod(), Type.DIRECT, descriptor.implHandle.isInterface);
+      return NoAccessorMethodTarget.create(descriptor);
     }
 
     // We need to generate an accessor method in `accessedFrom` class/interface for
@@ -520,20 +516,8 @@
             .dexItemFactory()
             .createMethod(
                 accessedFrom.getHolderType(), accessorProto, generateUniqueLambdaMethodName());
-    return new ClassMethodWithAccessorTarget(
-        descriptor.implHandle.asMethod(),
-        descriptor.implHandle.isInterface,
-        descriptor.implHandle.type,
-        accessorMethod,
-        appView);
-  }
-
-  // Create targets for interface methods.
-  private Target createInterfaceMethodTarget(ProgramMethod accessedFrom) {
-    assert descriptor.implHandle.type.isInvokeInterface();
-    assert doesNotNeedAccessor(accessedFrom);
-    return new NoAccessorMethodTarget(
-        descriptor.implHandle.asMethod(), Type.INTERFACE, descriptor.implHandle.isInterface);
+    return ClassMethodWithAccessorTarget.create(
+        descriptor.implHandle, accessedFrom, accessorMethod, appView);
   }
 
   private DexString generateUniqueLambdaMethodName() {
@@ -594,6 +578,13 @@
   // Used for targeting methods referenced directly without creating accessors.
   public static final class NoAccessorMethodTarget extends Target {
 
+    static NoAccessorMethodTarget create(LambdaDescriptor descriptor) {
+      return new NoAccessorMethodTarget(
+          descriptor.implHandle.asMethod(),
+          descriptor.implHandle.type.toInvokeType(),
+          descriptor.implHandle.isInterface);
+    }
+
     NoAccessorMethodTarget(DexMethod method, Type invokeType, boolean isInterface) {
       super(method, invokeType, isInterface);
     }
@@ -789,21 +780,37 @@
 
     private final AppView<?> appView;
     private final DexMethod implMethod;
+    private final boolean implMethodIsInterface;
     private final MethodHandleType type;
 
-    ClassMethodWithAccessorTarget(
+    static ClassMethodWithAccessorTarget create(
+        DexMethodHandle implHandle,
+        ProgramMethod accessedFrom,
+        DexMethod accessorMethod,
+        AppView<?> appView) {
+      return new ClassMethodWithAccessorTarget(
+          implHandle.asMethod(),
+          implHandle.isInterface,
+          implHandle.type,
+          accessorMethod,
+          accessedFrom.getHolder().isInterface(),
+          appView);
+    }
+
+    private ClassMethodWithAccessorTarget(
         DexMethod implMethod,
         boolean isInterface,
         MethodHandleType type,
         DexMethod accessorMethod,
+        boolean accessorIsInterface,
         AppView<?> appView) {
-      super(accessorMethod, Invoke.Type.STATIC, isInterface);
+      super(accessorMethod, Invoke.Type.STATIC, accessorIsInterface);
       this.appView = appView;
       this.implMethod = implMethod;
+      this.implMethodIsInterface = isInterface;
       this.type = type;
     }
 
-
     @Override
     ProgramMethod ensureAccessibility(
         ForcefullyMovedLambdaMethodConsumer forcefullyMovedLambdaMethodConsumer,
@@ -831,7 +838,7 @@
                   .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
                   .setCode(
                       AccessorMethodSourceCode.build(
-                          implMethod, isInterface, type, callTarget, appView))
+                          implMethod, implMethodIsInterface, type, callTarget, appView))
                   // The api level is computed when tracing.
                   .disableAndroidApiLevelCheck()
                   .build());
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
index d6b10b0..df7be1b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
@@ -203,15 +203,18 @@
 
   /** Checks if call site needs a accessor when referenced from `accessedFrom`. */
   boolean needsAccessor(ProgramMethod accessedFrom) {
-    if (implHandle.type.isInvokeInterface()) {
-      // Interface methods must be public.
+    // The invoke-interface may target a private method through nest based access in JDK 17.
+    // If the targetAccessFlags are missing we assume no accessor is needed since that was D8/R8's
+    // behavior prior to the introduction of bridges on invoke-interface.
+    if (implHandle.type.isInvokeInterface()
+        && (targetAccessFlags == null || targetAccessFlags.isPublic())) {
       return false;
     }
 
     boolean staticTarget = implHandle.type.isInvokeStatic();
     boolean instanceTarget = implHandle.type.isInvokeInstance() || implHandle.type.isInvokeDirect();
     boolean initTarget = implHandle.type.isInvokeConstructor();
-    assert instanceTarget || staticTarget || initTarget;
+    assert instanceTarget || staticTarget || initTarget || implHandle.type.isInvokeInterface();
     assert !implHandle.type.isInvokeDirect()
         || (targetAccessFlags.isPrivate()
             && !targetAccessFlags.isConstructor()
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index 3e41a70..c48cd2f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -137,7 +137,9 @@
     if (recordRewriter != null) {
       desugarings.add(recordRewriter);
     }
-    yieldingDesugarings.add(new UnrepresentableInDexInstructionRemover(appView));
+    if (appView.options().enableUnrepresentableInDexInstructionRemoval) {
+      yieldingDesugarings.add(new UnrepresentableInDexInstructionRemover(appView));
+    }
   }
 
   static NonEmptyCfInstructionDesugaringCollection createForCfToCfNonDesugar(AppView<?> appView) {
@@ -158,8 +160,10 @@
         new NonEmptyCfInstructionDesugaringCollection(appView, noAndroidApiLevelCompute());
     desugaringCollection.desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
     desugaringCollection.desugarings.add(new InvokeToPrivateRewriter());
-    desugaringCollection.yieldingDesugarings.add(
-        new UnrepresentableInDexInstructionRemover(appView));
+    if (appView.options().enableUnrepresentableInDexInstructionRemoval) {
+      desugaringCollection.yieldingDesugarings.add(
+          new UnrepresentableInDexInstructionRemover(appView));
+    }
     return desugaringCollection;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index 99b113d..bf643ae 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -47,7 +47,6 @@
 import com.android.tools.r8.ir.code.MemberType;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
 import java.util.ArrayDeque;
@@ -119,7 +118,7 @@
   }
 
   public static CfCode AtomicReferenceArrayMethods_compareAndSet(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -136,11 +135,10 @@
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType(
-                              "Ljava/util/concurrent/atomic/AtomicReferenceArray;")),
+                          factory.createType("Ljava/util/concurrent/atomic/AtomicReferenceArray;")),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.INT, 1),
@@ -148,15 +146,14 @@
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType(
-                        "Ljava/util/concurrent/atomic/AtomicReferenceArray;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.intType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("compareAndSet")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/concurrent/atomic/AtomicReferenceArray;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.intType,
+                        factory.objectType,
+                        factory.objectType),
+                    factory.createString("compareAndSet")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -168,22 +165,19 @@
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType(
-                              "Ljava/util/concurrent/atomic/AtomicReferenceArray;")),
+                          factory.createType("Ljava/util/concurrent/atomic/AtomicReferenceArray;")),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType(
-                        "Ljava/util/concurrent/atomic/AtomicReferenceArray;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.intType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/concurrent/atomic/AtomicReferenceArray;"),
+                    factory.createProto(factory.objectType, factory.intType),
+                    factory.createString("get")),
                 false),
             new CfLoad(ValueType.OBJECT, 2),
             new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label0),
@@ -196,7 +190,7 @@
   }
 
   public static CfCode AtomicReferenceFieldUpdaterMethods_compareAndSet(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -213,11 +207,11 @@
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType(
+                          factory.createType(
                               "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
@@ -225,15 +219,14 @@
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType(
-                        "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("compareAndSet")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.objectType,
+                        factory.objectType),
+                    factory.createString("compareAndSet")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -245,22 +238,20 @@
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType(
+                          factory.createType(
                               "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType(
-                        "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("get")),
                 false),
             new CfLoad(ValueType.OBJECT, 2),
             new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label0),
@@ -273,7 +264,7 @@
   }
 
   public static CfCode AtomicReferenceMethods_compareAndSet(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -290,23 +281,20 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType(
-                              "Ljava/util/concurrent/atomic/AtomicReference;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                          factory.createType("Ljava/util/concurrent/atomic/AtomicReference;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/concurrent/atomic/AtomicReference;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("compareAndSet")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/concurrent/atomic/AtomicReference;"),
+                    factory.createProto(
+                        factory.booleanType, factory.objectType, factory.objectType),
+                    factory.createString("compareAndSet")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -318,18 +306,17 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType(
-                              "Ljava/util/concurrent/atomic/AtomicReference;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                          factory.createType("Ljava/util/concurrent/atomic/AtomicReference;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/concurrent/atomic/AtomicReference;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/concurrent/atomic/AtomicReference;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("get")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
             new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label0),
@@ -341,7 +328,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode BooleanMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode BooleanMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -382,7 +369,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode BooleanMethods_hashCode(InternalOptions options, DexMethod method) {
+  public static CfCode BooleanMethods_hashCode(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -411,7 +398,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ByteMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode ByteMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -429,7 +416,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ByteMethods_compareUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode ByteMethods_compareUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -451,7 +438,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ByteMethods_toUnsignedInt(InternalOptions options, DexMethod method) {
+  public static CfCode ByteMethods_toUnsignedInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -469,7 +456,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ByteMethods_toUnsignedLong(InternalOptions options, DexMethod method) {
+  public static CfCode ByteMethods_toUnsignedLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -488,7 +475,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CharSequenceMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode CharSequenceMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -512,20 +499,20 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 true),
             new CfStore(ValueType.INT, 2),
             label1,
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 true),
             new CfStore(ValueType.INT, 3),
             label2,
@@ -540,8 +527,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -552,13 +539,10 @@
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("min")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Math;"),
+                    factory.createProto(factory.intType, factory.intType, factory.intType),
+                    factory.createString("min")),
                 false),
             new CfStore(ValueType.INT, 5),
             label6,
@@ -566,8 +550,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -581,11 +565,10 @@
             new CfLoad(ValueType.INT, 4),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfStore(ValueType.INT, 6),
             label8,
@@ -593,11 +576,10 @@
             new CfLoad(ValueType.INT, 4),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfStore(ValueType.INT, 7),
             label9,
@@ -614,8 +596,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -628,8 +610,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -642,7 +624,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CharacterMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode CharacterMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -661,7 +643,7 @@
   }
 
   public static CfCode CharacterMethods_toStringCodepoint(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -670,24 +652,22 @@
         1,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.stringType),
+            new CfNew(factory.stringType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charArrayType, options.itemFactory.intType),
-                    options.itemFactory.createString("toChars")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.charArrayType, factory.intType),
+                    factory.createString("toChars")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.charArrayType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.voidType, factory.charArrayType),
+                    factory.createString("<init>")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label1),
@@ -696,7 +676,7 @@
   }
 
   public static CfCode CloseResourceMethod_closeResourceImpl(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -726,17 +706,17 @@
         ImmutableList.of(
             label0,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.autoCloseableType),
+            new CfInstanceOf(factory.autoCloseableType),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.autoCloseableType),
+            new CfCheckCast(factory.autoCloseableType),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.autoCloseableType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("close")),
+                factory.createMethod(
+                    factory.autoCloseableType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("close")),
                 true),
             new CfGoto(label11),
             label2,
@@ -744,45 +724,45 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.classType),
-                    options.itemFactory.createString("getClass")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.classType),
+                    factory.createString("getClass")),
                 false),
-            new CfConstString(options.itemFactory.createString("close")),
+            new CfConstString(factory.createString("close")),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Class;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Class;")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.classType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                        options.itemFactory.stringType,
-                        options.itemFactory.createType("[Ljava/lang/Class;")),
-                    options.itemFactory.createString("getMethod")),
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(
+                        factory.createType("Ljava/lang/reflect/Method;"),
+                        factory.stringType,
+                        factory.createType("[Ljava/lang/Class;")),
+                    factory.createString("getMethod")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
             label3,
             new CfLoad(ValueType.OBJECT, 2),
             new CfLoad(ValueType.OBJECT, 1),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Object;")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
-                    options.itemFactory.createString("invoke")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/reflect/Method;"),
+                    factory.createProto(
+                        factory.objectType,
+                        factory.objectType,
+                        factory.createType("[Ljava/lang/Object;")),
+                    factory.createString("invoke")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label4,
@@ -792,68 +772,64 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType("Ljava/lang/Exception;"))))),
+                            factory.createType("Ljava/lang/Exception;"))))),
             new CfStore(ValueType.OBJECT, 2),
             label6,
-            new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
+            new CfNew(factory.createType("Ljava/lang/AssertionError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.classType),
-                    options.itemFactory.createString("getClass")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.classType),
+                    factory.createString("getClass")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.objectType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(" does not have a close() method.")),
+            new CfConstString(factory.createString(" does not have a close() method.")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/AssertionError;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.throwableType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/AssertionError;"),
+                    factory.createProto(
+                        factory.voidType, factory.stringType, factory.throwableType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label7,
@@ -861,67 +837,62 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(
-                    Arrays.asList(
-                        FrameType.initializedNonNullReference(options.itemFactory.throwableType)))),
+                    Arrays.asList(FrameType.initializedNonNullReference(factory.throwableType)))),
             new CfStore(ValueType.OBJECT, 2),
             label8,
-            new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
+            new CfNew(factory.createType("Ljava/lang/AssertionError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("Fail to call close() on ")),
+            new CfConstString(factory.createString("Fail to call close() on ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.classType),
-                    options.itemFactory.createString("getClass")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.classType),
+                    factory.createString("getClass")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.objectType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/AssertionError;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.throwableType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/AssertionError;"),
+                    factory.createProto(
+                        factory.voidType, factory.stringType, factory.throwableType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label9,
@@ -929,23 +900,22 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType(
-                                "Ljava/lang/reflect/InvocationTargetException;"))))),
+                            factory.createType("Ljava/lang/reflect/InvocationTargetException;"))))),
             new CfStore(ValueType.OBJECT, 2),
             label10,
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/InvocationTargetException;"),
-                    options.itemFactory.createProto(options.itemFactory.throwableType),
-                    options.itemFactory.createString("getCause")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/reflect/InvocationTargetException;"),
+                    factory.createProto(factory.throwableType),
+                    factory.createString("getCause")),
                 false),
             new CfThrow(),
             label11,
@@ -953,8 +923,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfGoto(label20),
             label12,
@@ -962,54 +932,53 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(
-                    Arrays.asList(
-                        FrameType.initializedNonNullReference(options.itemFactory.throwableType)))),
+                    Arrays.asList(FrameType.initializedNonNullReference(factory.throwableType)))),
             new CfStore(ValueType.OBJECT, 2),
             label13,
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.EQ, ValueType.OBJECT, label19),
             label14,
-            new CfConstClass(options.itemFactory.throwableType),
-            new CfConstString(options.itemFactory.createString("addSuppressed")),
+            new CfConstClass(factory.throwableType),
+            new CfConstString(factory.createString("addSuppressed")),
             new CfConstNumber(1, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Class;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Class;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstNumber(0, ValueType.INT),
-            new CfConstClass(options.itemFactory.throwableType),
+            new CfConstClass(factory.throwableType),
             new CfArrayStore(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.classType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                        options.itemFactory.stringType,
-                        options.itemFactory.createType("[Ljava/lang/Class;")),
-                    options.itemFactory.createString("getDeclaredMethod")),
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(
+                        factory.createType("Ljava/lang/reflect/Method;"),
+                        factory.stringType,
+                        factory.createType("[Ljava/lang/Class;")),
+                    factory.createString("getDeclaredMethod")),
                 false),
             new CfStore(ValueType.OBJECT, 3),
             label15,
             new CfLoad(ValueType.OBJECT, 3),
             new CfLoad(ValueType.OBJECT, 0),
             new CfConstNumber(1, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Object;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstNumber(0, ValueType.INT),
             new CfLoad(ValueType.OBJECT, 2),
             new CfArrayStore(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
-                    options.itemFactory.createString("invoke")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/reflect/Method;"),
+                    factory.createProto(
+                        factory.objectType,
+                        factory.objectType,
+                        factory.createType("[Ljava/lang/Object;")),
+                    factory.createString("invoke")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label16,
@@ -1019,23 +988,23 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.throwableType)
                     }),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType("Ljava/lang/Exception;"))))),
+                            factory.createType("Ljava/lang/Exception;"))))),
             new CfStore(ValueType.OBJECT, 3),
             label18,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.throwableType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfThrow(),
@@ -1044,9 +1013,9 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.throwableType)
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfThrow(),
@@ -1055,8 +1024,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfReturnVoid(),
             label21),
@@ -1064,53 +1033,48 @@
             new CfTryCatch(
                 label2,
                 label4,
-                ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/NoSuchMethodException;")),
+                ImmutableList.of(factory.createType("Ljava/lang/NoSuchMethodException;")),
                 ImmutableList.of(label5)),
             new CfTryCatch(
                 label2,
                 label4,
-                ImmutableList.of(options.itemFactory.createType("Ljava/lang/SecurityException;")),
+                ImmutableList.of(factory.createType("Ljava/lang/SecurityException;")),
                 ImmutableList.of(label5)),
             new CfTryCatch(
                 label2,
                 label4,
-                ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/IllegalAccessException;")),
+                ImmutableList.of(factory.createType("Ljava/lang/IllegalAccessException;")),
+                ImmutableList.of(label7)),
+            new CfTryCatch(
+                label2,
+                label4,
+                ImmutableList.of(factory.createType("Ljava/lang/IllegalArgumentException;")),
+                ImmutableList.of(label7)),
+            new CfTryCatch(
+                label2,
+                label4,
+                ImmutableList.of(factory.createType("Ljava/lang/ExceptionInInitializerError;")),
                 ImmutableList.of(label7)),
             new CfTryCatch(
                 label2,
                 label4,
                 ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
-                ImmutableList.of(label7)),
-            new CfTryCatch(
-                label2,
-                label4,
-                ImmutableList.of(
-                    options.itemFactory.createType("Ljava/lang/ExceptionInInitializerError;")),
-                ImmutableList.of(label7)),
-            new CfTryCatch(
-                label2,
-                label4,
-                ImmutableList.of(
-                    options.itemFactory.createType(
-                        "Ljava/lang/reflect/InvocationTargetException;")),
+                    factory.createType("Ljava/lang/reflect/InvocationTargetException;")),
                 ImmutableList.of(label9)),
             new CfTryCatch(
                 label0,
                 label11,
-                ImmutableList.of(options.itemFactory.throwableType),
+                ImmutableList.of(factory.throwableType),
                 ImmutableList.of(label12)),
             new CfTryCatch(
                 label14,
                 label16,
-                ImmutableList.of(options.itemFactory.createType("Ljava/lang/Exception;")),
+                ImmutableList.of(factory.createType("Ljava/lang/Exception;")),
                 ImmutableList.of(label17))),
         ImmutableList.of());
   }
 
-  public static CfCode CollectionMethods_listOfArray(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionMethods_listOfArray(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1124,17 +1088,16 @@
         6,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/ArrayList;")),
+            new CfNew(factory.createType("Ljava/util/ArrayList;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfArrayLength(),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/ArrayList;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
@@ -1151,11 +1114,11 @@
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/ArrayList;")),
+                          factory.createType("Ljava/util/ArrayList;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -1171,19 +1134,17 @@
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.objectType),
-                    options.itemFactory.createString("add")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/ArrayList;"),
+                    factory.createProto(factory.booleanType, factory.objectType),
+                    factory.createString("add")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label4,
@@ -1195,19 +1156,19 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/ArrayList;"))
+                          factory.createType("Ljava/util/ArrayList;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;"),
-                        options.itemFactory.createType("Ljava/util/List;")),
-                    options.itemFactory.createString("unmodifiableList")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/List;"),
+                        factory.createType("Ljava/util/List;")),
+                    factory.createString("unmodifiableList")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label6),
@@ -1215,7 +1176,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CollectionMethods_mapEntry(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionMethods_mapEntry(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1227,38 +1188,32 @@
         2,
         ImmutableList.of(
             label0,
-            new CfNew(
-                options.itemFactory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;")),
+            new CfNew(factory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             label1,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfLoad(ValueType.OBJECT, 1),
             label2,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;"),
+                    factory.createProto(factory.voidType, factory.objectType, factory.objectType),
+                    factory.createString("<init>")),
                 false),
             label3,
             new CfReturn(ValueType.OBJECT),
@@ -1267,7 +1222,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CollectionMethods_mapOfEntries(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionMethods_mapOfEntries(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1284,17 +1239,16 @@
         8,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashMap;")),
+            new CfNew(factory.createType("Ljava/util/HashMap;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfArrayLength(),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashMap;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
@@ -1311,11 +1265,11 @@
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+                          factory.createType("[Ljava/util/Map$Entry;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashMap;")),
+                          factory.createType("Ljava/util/HashMap;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+                          factory.createType("[Ljava/util/Map$Entry;")),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -1330,36 +1284,34 @@
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("getKey")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Map$Entry;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("getKey")),
                 true),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfStore(ValueType.OBJECT, 6),
             label4,
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("getValue")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Map$Entry;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("getValue")),
                 true),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfStore(ValueType.OBJECT, 7),
             label5,
@@ -1368,59 +1320,53 @@
             new CfLoad(ValueType.OBJECT, 7),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("put")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashMap;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.objectType),
+                    factory.createString("put")),
                 false),
             new CfIf(If.Type.EQ, ValueType.OBJECT, label7),
             label6,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfNew(factory.createType("Ljava/lang/IllegalArgumentException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("duplicate key: ")),
+            new CfConstString(factory.createString("duplicate key: ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 6),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.objectType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IllegalArgumentException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label7,
@@ -1429,11 +1375,11 @@
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+                          factory.createType("[Ljava/util/Map$Entry;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashMap;")),
+                          factory.createType("Ljava/util/HashMap;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+                          factory.createType("[Ljava/util/Map$Entry;")),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -1445,19 +1391,19 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+                          factory.createType("[Ljava/util/Map$Entry;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashMap;"))
+                          factory.createType("Ljava/util/HashMap;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Map;"),
-                        options.itemFactory.createType("Ljava/util/Map;")),
-                    options.itemFactory.createString("unmodifiableMap")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/Map;"),
+                        factory.createType("Ljava/util/Map;")),
+                    factory.createString("unmodifiableMap")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label9),
@@ -1465,7 +1411,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CollectionMethods_setOfArray(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionMethods_setOfArray(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1480,17 +1426,16 @@
         6,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashSet;")),
+            new CfNew(factory.createType("Ljava/util/HashSet;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfArrayLength(),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashSet;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
@@ -1507,11 +1452,11 @@
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashSet;")),
+                          factory.createType("Ljava/util/HashSet;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -1527,65 +1472,60 @@
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.objectType),
-                    options.itemFactory.createString("add")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashSet;"),
+                    factory.createProto(factory.booleanType, factory.objectType),
+                    factory.createString("add")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label5),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfNew(factory.createType("Ljava/lang/IllegalArgumentException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("duplicate element: ")),
+            new CfConstString(factory.createString("duplicate element: ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.objectType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IllegalArgumentException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5,
@@ -1594,11 +1534,11 @@
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashSet;")),
+                          factory.createType("Ljava/util/HashSet;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -1610,19 +1550,19 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
+                          factory.createType("[Ljava/lang/Object;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashSet;"))
+                          factory.createType("Ljava/util/HashSet;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Set;"),
-                        options.itemFactory.createType("Ljava/util/Set;")),
-                    options.itemFactory.createString("unmodifiableSet")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/Set;"),
+                        factory.createType("Ljava/util/Set;")),
+                    factory.createString("unmodifiableSet")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label7),
@@ -1630,7 +1570,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CollectionsMethods_copyOfList(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionsMethods_copyOfList(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1644,34 +1584,32 @@
         4,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/ArrayList;")),
+            new CfNew(factory.createType("Ljava/util/ArrayList;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("size")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collection;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("size")),
                 true),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/ArrayList;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
-                    options.itemFactory.createString("iterator")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collection;"),
+                    factory.createProto(factory.createType("Ljava/util/Iterator;")),
+                    factory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
             label2,
@@ -1680,28 +1618,28 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Collection;")),
+                          factory.createType("Ljava/util/Collection;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/ArrayList;")),
+                          factory.createType("Ljava/util/ArrayList;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Iterator;"))
+                          factory.createType("Ljava/util/Iterator;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("hasNext")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label5),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("next")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("next")),
                 true),
             new CfStore(ValueType.OBJECT, 3),
             label3,
@@ -1709,19 +1647,17 @@
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/ArrayList;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.objectType),
-                    options.itemFactory.createString("add")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/ArrayList;"),
+                    factory.createProto(factory.booleanType, factory.objectType),
+                    factory.createString("add")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label4,
@@ -1732,19 +1668,19 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Collection;")),
+                          factory.createType("Ljava/util/Collection;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/ArrayList;"))
+                          factory.createType("Ljava/util/ArrayList;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;"),
-                        options.itemFactory.createType("Ljava/util/List;")),
-                    options.itemFactory.createString("unmodifiableList")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/List;"),
+                        factory.createType("Ljava/util/List;")),
+                    factory.createString("unmodifiableList")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label6),
@@ -1752,7 +1688,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CollectionsMethods_copyOfMap(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionsMethods_copyOfMap(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1769,42 +1705,39 @@
         4,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashMap;")),
+            new CfNew(factory.createType("Ljava/util/HashMap;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map;"),
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("size")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Map;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("size")),
                 true),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashMap;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Set;")),
-                    options.itemFactory.createString("entrySet")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Map;"),
+                    factory.createProto(factory.createType("Ljava/util/Set;")),
+                    factory.createString("entrySet")),
                 true),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Set;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
-                    options.itemFactory.createString("iterator")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Set;"),
+                    factory.createProto(factory.createType("Ljava/util/Iterator;")),
+                    factory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
             label2,
@@ -1812,31 +1745,30 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
+                      FrameType.initializedNonNullReference(factory.createType("Ljava/util/Map;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Map;")),
+                          factory.createType("Ljava/util/HashMap;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashMap;")),
-                      FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Iterator;"))
+                          factory.createType("Ljava/util/Iterator;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("hasNext")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("next")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("next")),
                 true),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/Map$Entry;")),
+            new CfCheckCast(factory.createType("Ljava/util/Map$Entry;")),
             new CfStore(ValueType.OBJECT, 3),
             label3,
             new CfLoad(ValueType.OBJECT, 1),
@@ -1844,46 +1776,41 @@
             label4,
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("getKey")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Map$Entry;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("getKey")),
                 true),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfLoad(ValueType.OBJECT, 3),
             label5,
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Map$Entry;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("getValue")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Map$Entry;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("getValue")),
                 true),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             label6,
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashMap;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("put")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashMap;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.objectType),
+                    factory.createString("put")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label7,
@@ -1893,20 +1820,19 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
+                      FrameType.initializedNonNullReference(factory.createType("Ljava/util/Map;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Map;")),
-                      FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashMap;"))
+                          factory.createType("Ljava/util/HashMap;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Map;"),
-                        options.itemFactory.createType("Ljava/util/Map;")),
-                    options.itemFactory.createString("unmodifiableMap")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/Map;"),
+                        factory.createType("Ljava/util/Map;")),
+                    factory.createString("unmodifiableMap")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label9),
@@ -1914,7 +1840,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode CollectionsMethods_copyOfSet(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionsMethods_copyOfSet(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -1928,34 +1854,32 @@
         4,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/util/HashSet;")),
+            new CfNew(factory.createType("Ljava/util/HashSet;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("size")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collection;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("size")),
                 true),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashSet;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collection;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
-                    options.itemFactory.createString("iterator")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collection;"),
+                    factory.createProto(factory.createType("Ljava/util/Iterator;")),
+                    factory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
             label2,
@@ -1964,28 +1888,28 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Collection;")),
+                          factory.createType("Ljava/util/Collection;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashSet;")),
+                          factory.createType("Ljava/util/HashSet;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Iterator;"))
+                          factory.createType("Ljava/util/Iterator;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("hasNext")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label5),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("next")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("next")),
                 true),
             new CfStore(ValueType.OBJECT, 3),
             label3,
@@ -1993,19 +1917,17 @@
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/HashSet;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.objectType),
-                    options.itemFactory.createString("add")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/HashSet;"),
+                    factory.createProto(factory.booleanType, factory.objectType),
+                    factory.createString("add")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label4,
@@ -2016,19 +1938,19 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Collection;")),
+                          factory.createType("Ljava/util/Collection;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/HashSet;"))
+                          factory.createType("Ljava/util/HashSet;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Set;"),
-                        options.itemFactory.createType("Ljava/util/Set;")),
-                    options.itemFactory.createString("unmodifiableSet")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/Set;"),
+                        factory.createType("Ljava/util/Set;")),
+                    factory.createString("unmodifiableSet")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label6),
@@ -2037,7 +1959,7 @@
   }
 
   public static CfCode CollectionsMethods_emptyEnumeration(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     return new CfCode(
         method.holder,
@@ -2047,27 +1969,26 @@
             label0,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;")),
-                    options.itemFactory.createString("emptyList")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(factory.createType("Ljava/util/List;")),
+                    factory.createString("emptyList")),
                 false),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Enumeration;"),
-                        options.itemFactory.createType("Ljava/util/Collection;")),
-                    options.itemFactory.createString("enumeration")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/Enumeration;"),
+                        factory.createType("Ljava/util/Collection;")),
+                    factory.createString("enumeration")),
                 false),
             new CfReturn(ValueType.OBJECT)),
         ImmutableList.of(),
         ImmutableList.of());
   }
 
-  public static CfCode CollectionsMethods_emptyIterator(InternalOptions options, DexMethod method) {
+  public static CfCode CollectionsMethods_emptyIterator(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     return new CfCode(
         method.holder,
@@ -2077,19 +1998,17 @@
             label0,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;")),
-                    options.itemFactory.createString("emptyList")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(factory.createType("Ljava/util/List;")),
+                    factory.createString("emptyList")),
                 false),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/List;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
-                    options.itemFactory.createString("iterator")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/List;"),
+                    factory.createProto(factory.createType("Ljava/util/Iterator;")),
+                    factory.createString("iterator")),
                 true),
             new CfReturn(ValueType.OBJECT)),
         ImmutableList.of(),
@@ -2097,7 +2016,7 @@
   }
 
   public static CfCode CollectionsMethods_emptyListIterator(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     return new CfCode(
         method.holder,
@@ -2107,26 +2026,24 @@
             label0,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Collections;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/List;")),
-                    options.itemFactory.createString("emptyList")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Collections;"),
+                    factory.createProto(factory.createType("Ljava/util/List;")),
+                    factory.createString("emptyList")),
                 false),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/List;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/ListIterator;")),
-                    options.itemFactory.createString("listIterator")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/List;"),
+                    factory.createProto(factory.createType("Ljava/util/ListIterator;")),
+                    factory.createString("listIterator")),
                 true),
             new CfReturn(ValueType.OBJECT)),
         ImmutableList.of(),
         ImmutableList.of());
   }
 
-  public static CfCode DoubleMethods_hashCode(InternalOptions options, DexMethod method) {
+  public static CfCode DoubleMethods_hashCode(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2139,11 +2056,10 @@
             new CfLoad(ValueType.DOUBLE, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Double;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType, options.itemFactory.doubleType),
-                    options.itemFactory.createString("doubleToLongBits")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Double;"),
+                    factory.createProto(factory.longType, factory.doubleType),
+                    factory.createString("doubleToLongBits")),
                 false),
             new CfStore(ValueType.LONG, 2),
             label1,
@@ -2159,7 +2075,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode DoubleMethods_isFinite(InternalOptions options, DexMethod method) {
+  public static CfCode DoubleMethods_isFinite(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2173,21 +2089,19 @@
             new CfLoad(ValueType.DOUBLE, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Double;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.doubleType),
-                    options.itemFactory.createString("isInfinite")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Double;"),
+                    factory.createProto(factory.booleanType, factory.doubleType),
+                    factory.createString("isInfinite")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfLoad(ValueType.DOUBLE, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Double;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.doubleType),
-                    options.itemFactory.createString("isNaN")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Double;"),
+                    factory.createProto(factory.booleanType, factory.doubleType),
+                    factory.createString("isNaN")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(1, ValueType.INT),
@@ -2210,7 +2124,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode FloatMethods_isFinite(InternalOptions options, DexMethod method) {
+  public static CfCode FloatMethods_isFinite(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2224,21 +2138,19 @@
             new CfLoad(ValueType.FLOAT, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Float;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.floatType),
-                    options.itemFactory.createString("isInfinite")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Float;"),
+                    factory.createProto(factory.booleanType, factory.floatType),
+                    factory.createString("isInfinite")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfLoad(ValueType.FLOAT, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Float;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.floatType),
-                    options.itemFactory.createString("isNaN")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Float;"),
+                    factory.createProto(factory.booleanType, factory.floatType),
+                    factory.createString("isNaN")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(1, ValueType.INT),
@@ -2257,7 +2169,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2299,7 +2211,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_compareUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_compareUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2324,13 +2236,10 @@
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("compare")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType, factory.intType, factory.intType),
+                    factory.createString("compare")),
                 false),
             new CfReturn(ValueType.INT),
             label3),
@@ -2338,7 +2247,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_divideUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_divideUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2372,7 +2281,7 @@
   }
 
   public static CfCode IntegerMethods_parseIntSubsequenceWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -2386,31 +2295,25 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("subSequence")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charSequenceType, factory.intType, factory.intType),
+                    factory.createString("subSequence")),
                 true),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseInt")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType, factory.stringType, factory.intType),
+                    factory.createString("parseInt")),
                 false),
             new CfReturn(ValueType.INT),
             label1),
@@ -2419,7 +2322,7 @@
   }
 
   public static CfCode IntegerMethods_parseIntSubsequenceWithRadixDalvik(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2442,11 +2345,10 @@
             label1,
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfConstNumber(43, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label4),
@@ -2457,22 +2359,18 @@
             label2,
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.charType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("digit")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.charType, factory.intType),
+                    factory.createString("digit")),
                 false),
             new CfIf(If.Type.LT, ValueType.INT, label4),
             label3,
@@ -2482,7 +2380,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -2492,31 +2390,25 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("subSequence")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charSequenceType, factory.intType, factory.intType),
+                    factory.createString("subSequence")),
                 true),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseInt")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType, factory.stringType, factory.intType),
+                    factory.createString("parseInt")),
                 false),
             new CfReturn(ValueType.INT),
             label5),
@@ -2524,7 +2416,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_parseUnsignedInt(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_parseUnsignedInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -2537,13 +2429,10 @@
             new CfConstNumber(10, ValueType.INT),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseUnsignedInt")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType, factory.stringType, factory.intType),
+                    factory.createString("parseUnsignedInt")),
                 false),
             new CfReturn(ValueType.INT),
             label1),
@@ -2552,7 +2441,7 @@
   }
 
   public static CfCode IntegerMethods_parseUnsignedIntSubsequenceWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -2566,31 +2455,25 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("subSequence")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charSequenceType, factory.intType, factory.intType),
+                    factory.createString("subSequence")),
                 true),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseUnsignedInt")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType, factory.stringType, factory.intType),
+                    factory.createString("parseUnsignedInt")),
                 false),
             new CfReturn(ValueType.INT),
             label1),
@@ -2599,7 +2482,7 @@
   }
 
   public static CfCode IntegerMethods_parseUnsignedIntWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2616,10 +2499,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfConstNumber(1, ValueType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label2),
@@ -2627,11 +2510,10 @@
             new CfConstNumber(0, ValueType.INT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 false),
             new CfConstNumber(43, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
@@ -2640,11 +2522,10 @@
             new CfConstNumber(1, ValueType.INT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType, options.itemFactory.intType),
-                    options.itemFactory.createString("substring")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.intType),
+                    factory.createString("substring")),
                 false),
             new CfStore(ValueType.OBJECT, 0),
             label2,
@@ -2652,20 +2533,16 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
-                      FrameType.intType()
+                      FrameType.initializedNonNullReference(factory.stringType), FrameType.intType()
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.stringType, factory.intType),
+                    factory.createString("parseLong")),
                 false),
             new CfStore(ValueType.LONG, 2),
             label3,
@@ -2676,77 +2553,70 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.EQ, ValueType.INT, label5),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(factory.createType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("Input ")),
+            new CfConstString(factory.createString("Input ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(" in base ")),
+            new CfConstString(factory.createString(" in base ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(
-                options.itemFactory.createString(" is not in the range of an unsigned integer")),
+            new CfConstString(factory.createString(" is not in the range of an unsigned integer")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NumberFormatException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5,
@@ -2754,7 +2624,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.longType(),
                       FrameType.longHighType()
@@ -2767,7 +2637,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_remainderUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_remainderUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2800,7 +2670,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_toUnsignedLong(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_toUnsignedLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -2819,7 +2689,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode IntegerMethods_toUnsignedString(InternalOptions options, DexMethod method) {
+  public static CfCode IntegerMethods_toUnsignedString(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -2832,13 +2702,10 @@
             new CfConstNumber(10, ValueType.INT),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("toUnsignedString")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.stringType, factory.intType, factory.intType),
+                    factory.createString("toUnsignedString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label1),
@@ -2847,7 +2714,7 @@
   }
 
   public static CfCode IntegerMethods_toUnsignedStringWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2867,13 +2734,10 @@
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.longType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.stringType, factory.longType, factory.intType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label2),
@@ -2881,7 +2745,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_compareUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode LongMethods_compareUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -2906,13 +2770,10 @@
             new CfLoad(ValueType.LONG, 6),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("compare")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.intType, factory.longType, factory.longType),
+                    factory.createString("compare")),
                 false),
             new CfReturn(ValueType.INT),
             label3),
@@ -2920,7 +2781,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_divideUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode LongMethods_divideUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -3090,7 +2951,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_hashCode(InternalOptions options, DexMethod method) {
+  public static CfCode LongMethods_hashCode(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -3112,7 +2973,7 @@
   }
 
   public static CfCode LongMethods_parseLongSubsequenceWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -3126,31 +2987,25 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("subSequence")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charSequenceType, factory.intType, factory.intType),
+                    factory.createString("subSequence")),
                 true),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.stringType, factory.intType),
+                    factory.createString("parseLong")),
                 false),
             new CfReturn(ValueType.LONG),
             label1),
@@ -3159,7 +3014,7 @@
   }
 
   public static CfCode LongMethods_parseLongSubsequenceWithRadixDalvik(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -3182,11 +3037,10 @@
             label1,
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfConstNumber(43, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label4),
@@ -3197,22 +3051,18 @@
             label2,
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.charType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("digit")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.charType, factory.intType),
+                    factory.createString("digit")),
                 false),
             new CfIf(If.Type.LT, ValueType.INT, label4),
             label3,
@@ -3222,7 +3072,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -3232,31 +3082,25 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("subSequence")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charSequenceType, factory.intType, factory.intType),
+                    factory.createString("subSequence")),
                 true),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.stringType, factory.intType),
+                    factory.createString("parseLong")),
                 false),
             new CfReturn(ValueType.LONG),
             label5),
@@ -3264,7 +3108,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_parseUnsignedLong(InternalOptions options, DexMethod method) {
+  public static CfCode LongMethods_parseUnsignedLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -3277,13 +3121,10 @@
             new CfConstNumber(10, ValueType.INT),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseUnsignedLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.stringType, factory.intType),
+                    factory.createString("parseUnsignedLong")),
                 false),
             new CfReturn(ValueType.LONG),
             label1),
@@ -3292,7 +3133,7 @@
   }
 
   public static CfCode LongMethods_parseUnsignedLongSubsequenceWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -3329,16 +3170,15 @@
             new CfLoad(ValueType.INT, 4),
             new CfIf(If.Type.NE, ValueType.INT, label3),
             label2,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(factory.createType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfConstString(options.itemFactory.createString("empty string")),
+            new CfConstString(factory.createString("empty string")),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NumberFormatException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label3,
@@ -3346,7 +3186,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3363,39 +3203,36 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(factory.createType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfConstString(options.itemFactory.createString("illegal radix: ")),
+            new CfConstString(factory.createString("illegal radix: ")),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType, options.itemFactory.intType),
-                    options.itemFactory.createString("valueOf")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.intType),
+                    factory.createString("valueOf")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType, options.itemFactory.stringType),
-                    options.itemFactory.createString("concat")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.stringType),
+                    factory.createString("concat")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NumberFormatException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5,
@@ -3403,7 +3240,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3414,13 +3251,10 @@
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("divideUnsigned")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.longType, factory.longType),
+                    factory.createString("divideUnsigned")),
                 false),
             new CfStore(ValueType.LONG, 5),
             label6,
@@ -3428,11 +3262,10 @@
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfConstNumber(43, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label7),
@@ -3448,7 +3281,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3462,7 +3295,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3483,7 +3316,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3503,22 +3336,18 @@
             new CfLoad(ValueType.INT, 10),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType, options.itemFactory.intType),
-                    options.itemFactory.createString("charAt")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.charType, factory.intType),
+                    factory.createString("charAt")),
                 true),
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.charType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("digit")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.charType, factory.intType),
+                    factory.createString("digit")),
                 false),
             new CfStore(ValueType.INT, 11),
             label13,
@@ -3526,23 +3355,22 @@
             new CfConstNumber(-1, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label15),
             label14,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(factory.createType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NumberFormatException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label15,
@@ -3550,7 +3378,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3582,13 +3410,10 @@
             label16,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("remainderUnsigned")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.longType, factory.longType),
+                    factory.createString("remainderUnsigned")),
                 false),
             new CfNumberConversion(NumericType.LONG, NumericType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label18),
@@ -3597,7 +3422,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3610,32 +3435,30 @@
                       FrameType.intType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+            new CfNew(factory.createType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfConstString(options.itemFactory.createString("Too large for unsigned long: ")),
+            new CfConstString(factory.createString("Too large for unsigned long: ")),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.charSequenceType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.charSequenceType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 true),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType, options.itemFactory.stringType),
-                    options.itemFactory.createString("concat")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.stringType),
+                    factory.createString("concat")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NumberFormatException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label18,
@@ -3643,7 +3466,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3672,7 +3495,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType(),
@@ -3691,7 +3514,7 @@
   }
 
   public static CfCode LongMethods_parseUnsignedLongWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -3705,23 +3528,23 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("parseUnsignedLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(
+                        factory.longType,
+                        factory.charSequenceType,
+                        factory.intType,
+                        factory.intType,
+                        factory.intType),
+                    factory.createString("parseUnsignedLong")),
                 false),
             new CfReturn(ValueType.LONG),
             label1),
@@ -3729,7 +3552,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_remainderUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode LongMethods_remainderUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -3900,7 +3723,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_toUnsignedString(InternalOptions options, DexMethod method) {
+  public static CfCode LongMethods_toUnsignedString(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -3913,13 +3736,10 @@
             new CfConstNumber(10, ValueType.INT),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.longType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("toUnsignedString")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.stringType, factory.longType, factory.intType),
+                    factory.createString("toUnsignedString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label1),
@@ -3928,7 +3748,7 @@
   }
 
   public static CfCode LongMethods_toUnsignedStringWithRadix(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -3967,7 +3787,7 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfConstString(options.itemFactory.createString("0")),
+            new CfConstString(factory.createString("0")),
             new CfReturn(ValueType.OBJECT),
             label2,
             new CfFrame(
@@ -3985,13 +3805,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.longType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.stringType, factory.longType, factory.intType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label4,
@@ -4024,7 +3841,7 @@
                       FrameType.longType(), FrameType.longHighType(), FrameType.intType()
                     })),
             new CfConstNumber(64, ValueType.INT),
-            new CfNewArray(options.itemFactory.charArrayType),
+            new CfNewArray(factory.charArrayType),
             new CfStore(ValueType.OBJECT, 3),
             label7,
             new CfLoad(ValueType.OBJECT, 3),
@@ -4041,11 +3858,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Integer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("numberOfTrailingZeros")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("numberOfTrailingZeros")),
                 false),
             new CfStore(ValueType.INT, 5),
             label10,
@@ -4061,7 +3877,7 @@
                       FrameType.longType(),
                       FrameType.longHighType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.charArrayType),
+                      FrameType.initializedNonNullReference(factory.charArrayType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -4076,13 +3892,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("forDigit")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.charType, factory.intType, factory.intType),
+                    factory.createString("forDigit")),
                 false),
             new CfArrayStore(MemberType.CHAR),
             label12,
@@ -4105,7 +3918,7 @@
                       FrameType.longType(),
                       FrameType.longHighType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.charArrayType),
+                      FrameType.initializedNonNullReference(factory.charArrayType),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.INT, 2),
@@ -4132,7 +3945,7 @@
                       FrameType.longType(),
                       FrameType.longHighType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.charArrayType),
+                      FrameType.initializedNonNullReference(factory.charArrayType),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.LONG, 0),
@@ -4140,13 +3953,10 @@
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("divideUnsigned")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType, factory.longType, factory.longType),
+                    factory.createString("divideUnsigned")),
                 false),
             new CfStore(ValueType.LONG, 5),
             label19,
@@ -4157,7 +3967,7 @@
                       FrameType.longType(),
                       FrameType.longHighType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.charArrayType),
+                      FrameType.initializedNonNullReference(factory.charArrayType),
                       FrameType.intType(),
                       FrameType.longType(),
                       FrameType.longHighType()
@@ -4178,13 +3988,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("forDigit")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.charType, factory.intType, factory.intType),
+                    factory.createString("forDigit")),
                 false),
             new CfArrayStore(MemberType.CHAR),
             label21,
@@ -4198,7 +4005,7 @@
                       FrameType.longType(),
                       FrameType.longHighType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.charArrayType),
+                      FrameType.initializedNonNullReference(factory.charArrayType),
                       FrameType.intType(),
                       FrameType.longType(),
                       FrameType.longHighType(),
@@ -4221,13 +4028,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.charType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("forDigit")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.charType, factory.intType, factory.intType),
+                    factory.createString("forDigit")),
                 false),
             new CfArrayStore(MemberType.CHAR),
             label24,
@@ -4245,10 +4049,10 @@
                       FrameType.longType(),
                       FrameType.longHighType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.charArrayType),
+                      FrameType.initializedNonNullReference(factory.charArrayType),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.stringType),
+            new CfNew(factory.stringType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 3),
             new CfLoad(ValueType.INT, 4),
@@ -4258,14 +4062,11 @@
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType,
-                        options.itemFactory.charArrayType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(
+                        factory.voidType, factory.charArrayType, factory.intType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label26),
@@ -4273,7 +4074,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_addExactInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_addExactInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4316,14 +4117,14 @@
                       FrameType.longHighType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5),
@@ -4331,7 +4132,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_addExactLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_addExactLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4438,14 +4239,14 @@
                       FrameType.longType(),
                       FrameType.longHighType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label8),
@@ -4453,7 +4254,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_decrementExactInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_decrementExactInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4468,14 +4269,14 @@
             new CfConstNumber(-2147483648, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -4490,7 +4291,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_decrementExactLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_decrementExactLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4506,14 +4307,14 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -4530,7 +4331,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_floorDivInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_floorDivInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4618,7 +4419,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_floorDivLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_floorDivLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4724,7 +4525,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_floorDivLongInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_floorDivLongInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -4738,13 +4539,10 @@
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("floorDiv")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Math;"),
+                    factory.createProto(factory.longType, factory.longType, factory.longType),
+                    factory.createString("floorDiv")),
                 false),
             new CfReturn(ValueType.LONG),
             label1),
@@ -4752,7 +4550,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_floorModInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_floorModInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4827,7 +4625,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_floorModLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_floorModLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4919,7 +4717,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_floorModLongInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_floorModLongInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -4933,13 +4731,10 @@
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("floorMod")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Math;"),
+                    factory.createProto(factory.longType, factory.longType, factory.longType),
+                    factory.createString("floorMod")),
                 false),
             new CfNumberConversion(NumericType.LONG, NumericType.INT),
             new CfReturn(ValueType.INT),
@@ -4948,7 +4743,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_incrementExactInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_incrementExactInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -4963,14 +4758,14 @@
             new CfConstNumber(2147483647, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -4985,7 +4780,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_incrementExactLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_incrementExactLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5001,14 +4796,14 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -5025,7 +4820,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_multiplyExactInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_multiplyExactInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5068,14 +4863,14 @@
                       FrameType.longHighType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5),
@@ -5083,7 +4878,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_multiplyExactLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_multiplyExactLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5111,11 +4906,10 @@
             label1,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.longType),
-                    options.itemFactory.createString("numberOfLeadingZeros")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.intType, factory.longType),
+                    factory.createString("numberOfLeadingZeros")),
                 false),
             new CfLoad(ValueType.LONG, 0),
             new CfConstNumber(-1, ValueType.LONG),
@@ -5123,22 +4917,20 @@
             label2,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.longType),
-                    options.itemFactory.createString("numberOfLeadingZeros")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.intType, factory.longType),
+                    factory.createString("numberOfLeadingZeros")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfLoad(ValueType.LONG, 2),
             label3,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.longType),
-                    options.itemFactory.createString("numberOfLeadingZeros")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.intType, factory.longType),
+                    factory.createString("numberOfLeadingZeros")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfLoad(ValueType.LONG, 2),
@@ -5147,11 +4939,10 @@
             label4,
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Long;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.longType),
-                    options.itemFactory.createString("numberOfLeadingZeros")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.intType, factory.longType),
+                    factory.createString("numberOfLeadingZeros")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfStore(ValueType.INT, 4),
@@ -5283,14 +5074,14 @@
                       FrameType.longHighType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label16),
@@ -5298,7 +5089,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_multiplyExactLongInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_multiplyExactLongInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -5312,13 +5103,10 @@
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.longType,
-                        options.itemFactory.longType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("multiplyExact")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Math;"),
+                    factory.createProto(factory.longType, factory.longType, factory.longType),
+                    factory.createString("multiplyExact")),
                 false),
             new CfReturn(ValueType.LONG),
             label1),
@@ -5326,7 +5114,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_multiplyFull(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_multiplyFull(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -5346,7 +5134,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_multiplyHigh(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_multiplyHigh(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5450,7 +5238,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_negateExactInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_negateExactInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5465,14 +5253,14 @@
             new CfConstNumber(-2147483648, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -5486,7 +5274,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_negateExactLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_negateExactLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5502,14 +5290,14 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -5525,7 +5313,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_nextDownDouble(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_nextDownDouble(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -5538,11 +5326,10 @@
             new CfNeg(NumericType.DOUBLE),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.doubleType, options.itemFactory.doubleType),
-                    options.itemFactory.createString("nextUp")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Math;"),
+                    factory.createProto(factory.doubleType, factory.doubleType),
+                    factory.createString("nextUp")),
                 false),
             new CfNeg(NumericType.DOUBLE),
             new CfReturn(ValueType.DOUBLE),
@@ -5551,7 +5338,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_nextDownFloat(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_nextDownFloat(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -5564,11 +5351,10 @@
             new CfNeg(NumericType.FLOAT),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Math;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.floatType, options.itemFactory.floatType),
-                    options.itemFactory.createString("nextUp")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Math;"),
+                    factory.createProto(factory.floatType, factory.floatType),
+                    factory.createString("nextUp")),
                 false),
             new CfNeg(NumericType.FLOAT),
             new CfReturn(ValueType.FLOAT),
@@ -5577,7 +5363,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_subtractExactInt(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_subtractExactInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5620,14 +5406,14 @@
                       FrameType.longHighType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5),
@@ -5635,7 +5421,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_subtractExactLong(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_subtractExactLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5742,14 +5528,14 @@
                       FrameType.longType(),
                       FrameType.longHighType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label8),
@@ -5757,7 +5543,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode MathMethods_toIntExact(InternalOptions options, DexMethod method) {
+  public static CfCode MathMethods_toIntExact(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5779,14 +5565,14 @@
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.EQ, ValueType.INT, label3),
             label2,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+            new CfNew(factory.createType("Ljava/lang/ArithmeticException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ArithmeticException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label3,
@@ -5803,8 +5589,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_checkFromIndexSize(
-      InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_checkFromIndexSize(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5833,103 +5618,94 @@
                     new FrameType[] {
                       FrameType.intType(), FrameType.intType(), FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+            new CfNew(factory.createType("Ljava/lang/IndexOutOfBoundsException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("Range [")),
+            new CfConstString(factory.createString("Range [")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(", ")),
+            new CfConstString(factory.createString(", ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(" + ")),
+            new CfConstString(factory.createString(" + ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(") out of bounds for length ")),
+            new CfConstString(factory.createString(") out of bounds for length ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -5946,7 +5722,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_checkFromToIndex(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_checkFromToIndex(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -5972,85 +5748,78 @@
                     new FrameType[] {
                       FrameType.intType(), FrameType.intType(), FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+            new CfNew(factory.createType("Ljava/lang/IndexOutOfBoundsException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("Range [")),
+            new CfConstString(factory.createString("Range [")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(", ")),
+            new CfConstString(factory.createString(", ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(") out of bounds for length ")),
+            new CfConstString(factory.createString(") out of bounds for length ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -6067,7 +5836,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_checkIndex(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_checkIndex(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6087,67 +5856,62 @@
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1}, new FrameType[] {FrameType.intType(), FrameType.intType()})),
-            new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+            new CfNew(factory.createType("Ljava/lang/IndexOutOfBoundsException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("Index ")),
+            new CfConstString(factory.createString("Index ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(" out of bounds for length ")),
+            new CfConstString(factory.createString(" out of bounds for length ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -6161,7 +5925,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6182,33 +5946,30 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Comparator;"))
+                          factory.createType("Ljava/util/Comparator;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Comparator;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("compare")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Comparator;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.objectType),
+                    factory.createString("compare")),
                 true),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Comparator;"))
+                          factory.createType("Ljava/util/Comparator;"))
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6217,7 +5978,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_deepEquals(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_deepEquals(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6274,8 +6035,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label2),
@@ -6286,29 +6047,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.booleanArrayType),
+            new CfInstanceOf(factory.booleanArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label6),
             label3,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.booleanArrayType),
+            new CfInstanceOf(factory.booleanArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label4),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.booleanArrayType),
+            new CfCheckCast(factory.booleanArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.booleanArrayType),
+            new CfCheckCast(factory.booleanArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.booleanArrayType,
-                        options.itemFactory.booleanArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.booleanArrayType, factory.booleanArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label4),
             new CfConstNumber(1, ValueType.INT),
@@ -6318,8 +6077,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label5,
@@ -6327,8 +6086,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6337,29 +6096,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.byteArrayType),
+            new CfInstanceOf(factory.byteArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label10),
             label7,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.byteArrayType),
+            new CfInstanceOf(factory.byteArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.byteArrayType),
+            new CfCheckCast(factory.byteArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.byteArrayType),
+            new CfCheckCast(factory.byteArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.byteArrayType,
-                        options.itemFactory.byteArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.byteArrayType, factory.byteArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
             new CfConstNumber(1, ValueType.INT),
@@ -6369,8 +6126,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label9,
@@ -6378,8 +6135,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6388,29 +6145,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.charArrayType),
+            new CfInstanceOf(factory.charArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label14),
             label11,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.charArrayType),
+            new CfInstanceOf(factory.charArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label12),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.charArrayType),
+            new CfCheckCast(factory.charArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.charArrayType),
+            new CfCheckCast(factory.charArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.charArrayType,
-                        options.itemFactory.charArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.charArrayType, factory.charArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label12),
             new CfConstNumber(1, ValueType.INT),
@@ -6420,8 +6175,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label13,
@@ -6429,8 +6184,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6439,29 +6194,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.doubleArrayType),
+            new CfInstanceOf(factory.doubleArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label18),
             label15,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.doubleArrayType),
+            new CfInstanceOf(factory.doubleArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label16),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.doubleArrayType),
+            new CfCheckCast(factory.doubleArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.doubleArrayType),
+            new CfCheckCast(factory.doubleArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.doubleArrayType,
-                        options.itemFactory.doubleArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.doubleArrayType, factory.doubleArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label16),
             new CfConstNumber(1, ValueType.INT),
@@ -6471,8 +6224,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label17,
@@ -6480,8 +6233,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6490,29 +6243,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.floatArrayType),
+            new CfInstanceOf(factory.floatArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label22),
             label19,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.floatArrayType),
+            new CfInstanceOf(factory.floatArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label20),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.floatArrayType),
+            new CfCheckCast(factory.floatArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.floatArrayType),
+            new CfCheckCast(factory.floatArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.floatArrayType,
-                        options.itemFactory.floatArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.floatArrayType, factory.floatArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label20),
             new CfConstNumber(1, ValueType.INT),
@@ -6522,8 +6273,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label21,
@@ -6531,8 +6282,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6541,29 +6292,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.intArrayType),
+            new CfInstanceOf(factory.intArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label26),
             label23,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.intArrayType),
+            new CfInstanceOf(factory.intArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label24),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.intArrayType),
+            new CfCheckCast(factory.intArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.intArrayType),
+            new CfCheckCast(factory.intArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.intArrayType,
-                        options.itemFactory.intArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.intArrayType, factory.intArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label24),
             new CfConstNumber(1, ValueType.INT),
@@ -6573,8 +6322,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label25,
@@ -6582,8 +6331,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6592,29 +6341,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.longArrayType),
+            new CfInstanceOf(factory.longArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label30),
             label27,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.longArrayType),
+            new CfInstanceOf(factory.longArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label28),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.longArrayType),
+            new CfCheckCast(factory.longArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.longArrayType),
+            new CfCheckCast(factory.longArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.longArrayType,
-                        options.itemFactory.longArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.longArrayType, factory.longArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label28),
             new CfConstNumber(1, ValueType.INT),
@@ -6624,8 +6371,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label29,
@@ -6633,8 +6380,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6643,29 +6390,27 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.shortArrayType),
+            new CfInstanceOf(factory.shortArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label34),
             label31,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.shortArrayType),
+            new CfInstanceOf(factory.shortArrayType),
             new CfIf(If.Type.EQ, ValueType.INT, label32),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.shortArrayType),
+            new CfCheckCast(factory.shortArrayType),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.shortArrayType),
+            new CfCheckCast(factory.shortArrayType),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.shortArrayType,
-                        options.itemFactory.shortArrayType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType, factory.shortArrayType, factory.shortArrayType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label32),
             new CfConstNumber(1, ValueType.INT),
@@ -6675,8 +6420,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label33,
@@ -6684,8 +6429,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6694,29 +6439,29 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfInstanceOf(factory.createType("[Ljava/lang/Object;")),
             new CfIf(If.Type.EQ, ValueType.INT, label38),
             label35,
             new CfLoad(ValueType.OBJECT, 1),
-            new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfInstanceOf(factory.createType("[Ljava/lang/Object;")),
             new CfIf(If.Type.EQ, ValueType.INT, label36),
             new CfLoad(ValueType.OBJECT, 0),
-            new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfCheckCast(factory.createType("[Ljava/lang/Object;")),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfCheckCast(factory.createType("[Ljava/lang/Object;")),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.createType("[Ljava/lang/Object;"),
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
-                    options.itemFactory.createString("deepEquals")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.createType("[Ljava/lang/Object;"),
+                        factory.createType("[Ljava/lang/Object;")),
+                    factory.createString("deepEquals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label36),
             new CfConstNumber(1, ValueType.INT),
@@ -6726,8 +6471,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label37,
@@ -6735,8 +6480,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6745,18 +6490,17 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.objectType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.booleanType, factory.objectType),
+                    factory.createString("equals")),
                 false),
             new CfReturn(ValueType.INT),
             label39),
@@ -6764,7 +6508,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_equals(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_equals(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6785,11 +6529,10 @@
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.objectType),
-                    options.itemFactory.createString("equals")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.booleanType, factory.objectType),
+                    factory.createString("equals")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -6797,8 +6540,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(1, ValueType.INT),
             new CfGoto(label3),
@@ -6807,8 +6550,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfConstNumber(0, ValueType.INT),
             label3,
@@ -6816,8 +6559,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -6826,7 +6569,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_hashCode(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_hashCode(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6845,24 +6588,20 @@
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)})),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("hashCode")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.intType),
+                    factory.createString("hashCode")),
                 false),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    }),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)}),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
             label3),
@@ -6870,7 +6609,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_isNull(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_isNull(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6889,17 +6628,13 @@
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)})),
             new CfConstNumber(0, ValueType.INT),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    }),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)}),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
             label3),
@@ -6907,7 +6642,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_nonNull(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_nonNull(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6926,17 +6661,13 @@
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)})),
             new CfConstNumber(0, ValueType.INT),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    }),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)}),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
             label3),
@@ -6944,8 +6675,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_requireNonNullElse(
-      InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_requireNonNullElse(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -6964,20 +6694,17 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfConstString(options.itemFactory.createString("defaultObj")),
+            new CfConstString(factory.createString("defaultObj")),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.stringType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.stringType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label2),
@@ -6986,7 +6713,7 @@
   }
 
   public static CfCode ObjectsMethods_requireNonNullElseGet(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7006,43 +6733,37 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Supplier;"))
+                          factory.createType("Ljava/util/function/Supplier;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
-            new CfConstString(options.itemFactory.createString("supplier")),
+            new CfConstString(factory.createString("supplier")),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.stringType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.stringType),
+                    factory.createString("requireNonNull")),
                 false),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/function/Supplier;")),
+            new CfCheckCast(factory.createType("Ljava/util/function/Supplier;")),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Supplier;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/Supplier;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("get")),
                 true),
             new CfStore(ValueType.OBJECT, 2),
             label2,
             new CfLoad(ValueType.OBJECT, 2),
-            new CfConstString(options.itemFactory.createString("supplier.get()")),
+            new CfConstString(factory.createString("supplier.get()")),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.stringType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.stringType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label3),
@@ -7051,7 +6772,7 @@
   }
 
   public static CfCode ObjectsMethods_requireNonNullMessage(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7065,16 +6786,15 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -7082,8 +6802,8 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.stringType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfReturn(ValueType.OBJECT),
@@ -7093,7 +6813,7 @@
   }
 
   public static CfCode ObjectsMethods_requireNonNullSupplier(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7115,21 +6835,21 @@
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Supplier;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/Supplier;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("get")),
                 true),
-            new CfCheckCast(options.itemFactory.stringType),
+            new CfCheckCast(factory.stringType),
             new CfGoto(label3),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Supplier;"))
+                          factory.createType("Ljava/util/function/Supplier;"))
                     })),
             new CfConstNull(),
             label3,
@@ -7137,25 +6857,23 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Supplier;"))
+                          factory.createType("Ljava/util/function/Supplier;"))
                     }),
                 new ArrayDeque<>(
-                    Arrays.asList(
-                        FrameType.initializedNonNullReference(options.itemFactory.stringType)))),
+                    Arrays.asList(FrameType.initializedNonNullReference(factory.stringType)))),
             new CfStore(ValueType.OBJECT, 2),
             label4,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label5,
@@ -7163,9 +6881,9 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Supplier;"))
+                          factory.createType("Ljava/util/function/Supplier;"))
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfReturn(ValueType.OBJECT),
@@ -7174,7 +6892,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_toString(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_toString(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -7184,16 +6902,13 @@
         ImmutableList.of(
             label0,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfConstString(options.itemFactory.createString("null")),
+            new CfConstString(factory.createString("null")),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.stringType, factory.objectType, factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label1),
@@ -7201,7 +6916,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ObjectsMethods_toStringDefault(InternalOptions options, DexMethod method) {
+  public static CfCode ObjectsMethods_toStringDefault(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7221,35 +6936,34 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.stringType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.stringType)
                     }),
                 new ArrayDeque<>(
-                    Arrays.asList(
-                        FrameType.initializedNonNullReference(options.itemFactory.stringType)))),
+                    Arrays.asList(FrameType.initializedNonNullReference(factory.stringType)))),
             new CfReturn(ValueType.OBJECT),
             label3),
         ImmutableList.of(),
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_ifPresentOrElse(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_ifPresentOrElse(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7264,10 +6978,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Optional;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -7275,18 +6989,17 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Optional;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("get")),
                 false),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Consumer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.objectType),
-                    options.itemFactory.createString("accept")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/Consumer;"),
+                    factory.createProto(factory.voidType, factory.objectType),
+                    factory.createString("accept")),
                 true),
             new CfGoto(label3),
             label2,
@@ -7295,19 +7008,19 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Optional;")),
+                          factory.createType("Ljava/util/Optional;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Consumer;")),
+                          factory.createType("Ljava/util/function/Consumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("run")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Runnable;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("run")),
                 true),
             label3,
             new CfFrame(
@@ -7315,11 +7028,11 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Optional;")),
+                          factory.createType("Ljava/util/Optional;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Consumer;")),
+                          factory.createType("Ljava/util/function/Consumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfReturnVoid(),
             label4),
@@ -7328,7 +7041,7 @@
   }
 
   public static CfCode OptionalMethods_ifPresentOrElseDouble(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7343,10 +7056,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalDouble;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -7354,18 +7067,17 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.doubleType),
-                    options.itemFactory.createString("getAsDouble")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalDouble;"),
+                    factory.createProto(factory.doubleType),
+                    factory.createString("getAsDouble")),
                 false),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/DoubleConsumer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.doubleType),
-                    options.itemFactory.createString("accept")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/DoubleConsumer;"),
+                    factory.createProto(factory.voidType, factory.doubleType),
+                    factory.createString("accept")),
                 true),
             new CfGoto(label3),
             label2,
@@ -7374,19 +7086,19 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalDouble;")),
+                          factory.createType("Ljava/util/OptionalDouble;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/DoubleConsumer;")),
+                          factory.createType("Ljava/util/function/DoubleConsumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("run")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Runnable;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("run")),
                 true),
             label3,
             new CfFrame(
@@ -7394,11 +7106,11 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalDouble;")),
+                          factory.createType("Ljava/util/OptionalDouble;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/DoubleConsumer;")),
+                          factory.createType("Ljava/util/function/DoubleConsumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfReturnVoid(),
             label4),
@@ -7407,7 +7119,7 @@
   }
 
   public static CfCode OptionalMethods_ifPresentOrElseInt(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7422,10 +7134,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalInt;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -7433,18 +7145,17 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("getAsInt")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalInt;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("getAsInt")),
                 false),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/IntConsumer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("accept")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/IntConsumer;"),
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("accept")),
                 true),
             new CfGoto(label3),
             label2,
@@ -7453,19 +7164,19 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalInt;")),
+                          factory.createType("Ljava/util/OptionalInt;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/IntConsumer;")),
+                          factory.createType("Ljava/util/function/IntConsumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("run")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Runnable;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("run")),
                 true),
             label3,
             new CfFrame(
@@ -7473,11 +7184,11 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalInt;")),
+                          factory.createType("Ljava/util/OptionalInt;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/IntConsumer;")),
+                          factory.createType("Ljava/util/function/IntConsumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfReturnVoid(),
             label4),
@@ -7486,7 +7197,7 @@
   }
 
   public static CfCode OptionalMethods_ifPresentOrElseLong(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7501,10 +7212,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalLong;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -7512,18 +7223,17 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.longType),
-                    options.itemFactory.createString("getAsLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalLong;"),
+                    factory.createProto(factory.longType),
+                    factory.createString("getAsLong")),
                 false),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/LongConsumer;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.longType),
-                    options.itemFactory.createString("accept")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/LongConsumer;"),
+                    factory.createProto(factory.voidType, factory.longType),
+                    factory.createString("accept")),
                 true),
             new CfGoto(label3),
             label2,
@@ -7532,19 +7242,19 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalLong;")),
+                          factory.createType("Ljava/util/OptionalLong;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/LongConsumer;")),
+                          factory.createType("Ljava/util/function/LongConsumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Runnable;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("run")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Runnable;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("run")),
                 true),
             label3,
             new CfFrame(
@@ -7552,11 +7262,11 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalLong;")),
+                          factory.createType("Ljava/util/OptionalLong;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/LongConsumer;")),
+                          factory.createType("Ljava/util/function/LongConsumer;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Runnable;"))
+                          factory.createType("Ljava/lang/Runnable;"))
                     })),
             new CfReturnVoid(),
             label4),
@@ -7564,7 +7274,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_isEmpty(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_isEmpty(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7578,10 +7288,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Optional;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(1, ValueType.INT),
@@ -7592,7 +7302,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Optional;"))
+                          factory.createType("Ljava/util/Optional;"))
                     })),
             new CfConstNumber(0, ValueType.INT),
             label2,
@@ -7601,7 +7311,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Optional;"))
+                          factory.createType("Ljava/util/Optional;"))
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -7610,7 +7320,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_isEmptyDouble(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_isEmptyDouble(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7624,10 +7334,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalDouble;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(1, ValueType.INT),
@@ -7638,7 +7348,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalDouble;"))
+                          factory.createType("Ljava/util/OptionalDouble;"))
                     })),
             new CfConstNumber(0, ValueType.INT),
             label2,
@@ -7647,7 +7357,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalDouble;"))
+                          factory.createType("Ljava/util/OptionalDouble;"))
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -7656,7 +7366,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_isEmptyInt(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_isEmptyInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7670,10 +7380,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalInt;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(1, ValueType.INT),
@@ -7684,7 +7394,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalInt;"))
+                          factory.createType("Ljava/util/OptionalInt;"))
                     })),
             new CfConstNumber(0, ValueType.INT),
             label2,
@@ -7693,7 +7403,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalInt;"))
+                          factory.createType("Ljava/util/OptionalInt;"))
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -7702,7 +7412,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_isEmptyLong(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_isEmptyLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7716,10 +7426,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalLong;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(1, ValueType.INT),
@@ -7730,7 +7440,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalLong;"))
+                          factory.createType("Ljava/util/OptionalLong;"))
                     })),
             new CfConstNumber(0, ValueType.INT),
             label2,
@@ -7739,7 +7449,7 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalLong;"))
+                          factory.createType("Ljava/util/OptionalLong;"))
                     }),
                 new ArrayDeque<>(Arrays.asList(FrameType.intType()))),
             new CfReturn(ValueType.INT),
@@ -7748,7 +7458,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_or(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_or(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7764,21 +7474,20 @@
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Optional;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label3),
             label2,
@@ -7790,38 +7499,37 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Optional;")),
+                          factory.createType("Ljava/util/Optional;")),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/function/Supplier;"))
+                          factory.createType("Ljava/util/function/Supplier;"))
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Supplier;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/Supplier;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("get")),
                 true),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/Optional;")),
+            new CfCheckCast(factory.createType("Ljava/util/Optional;")),
             new CfStore(ValueType.OBJECT, 2),
             label4,
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Objects;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType, options.itemFactory.objectType),
-                    options.itemFactory.createString("requireNonNull")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Objects;"),
+                    factory.createProto(factory.objectType, factory.objectType),
+                    factory.createString("requireNonNull")),
                 false),
-            new CfCheckCast(options.itemFactory.createType("Ljava/util/Optional;")),
+            new CfCheckCast(factory.createType("Ljava/util/Optional;")),
             new CfReturn(ValueType.OBJECT),
             label5),
         ImmutableList.of(),
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_stream(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_stream(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7835,29 +7543,28 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Optional;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Optional;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("get")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Optional;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("get")),
                 false),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("of")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/Stream;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/stream/Stream;"), factory.objectType),
+                    factory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label2,
@@ -7866,15 +7573,14 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Optional;"))
+                          factory.createType("Ljava/util/Optional;"))
                     })),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;")),
-                    options.itemFactory.createString("empty")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/Stream;"),
+                    factory.createProto(factory.createType("Ljava/util/stream/Stream;")),
+                    factory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label3),
@@ -7882,7 +7588,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_streamDouble(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_streamDouble(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7896,29 +7602,28 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalDouble;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalDouble;"),
-                    options.itemFactory.createProto(options.itemFactory.doubleType),
-                    options.itemFactory.createString("getAsDouble")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalDouble;"),
+                    factory.createProto(factory.doubleType),
+                    factory.createString("getAsDouble")),
                 false),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
-                        options.itemFactory.doubleType),
-                    options.itemFactory.createString("of")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/DoubleStream;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/stream/DoubleStream;"), factory.doubleType),
+                    factory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label2,
@@ -7927,15 +7632,14 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalDouble;"))
+                          factory.createType("Ljava/util/OptionalDouble;"))
                     })),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/DoubleStream;")),
-                    options.itemFactory.createString("empty")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/DoubleStream;"),
+                    factory.createProto(factory.createType("Ljava/util/stream/DoubleStream;")),
+                    factory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label3),
@@ -7943,7 +7647,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_streamInt(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_streamInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -7957,29 +7661,28 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalInt;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalInt;"),
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("getAsInt")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalInt;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("getAsInt")),
                 false),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/IntStream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/IntStream;"),
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("of")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/IntStream;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/stream/IntStream;"), factory.intType),
+                    factory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label2,
@@ -7988,15 +7691,14 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalInt;"))
+                          factory.createType("Ljava/util/OptionalInt;"))
                     })),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/IntStream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/IntStream;")),
-                    options.itemFactory.createString("empty")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/IntStream;"),
+                    factory.createProto(factory.createType("Ljava/util/stream/IntStream;")),
+                    factory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label3),
@@ -8004,7 +7706,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode OptionalMethods_streamLong(InternalOptions options, DexMethod method) {
+  public static CfCode OptionalMethods_streamLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8018,29 +7720,28 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("isPresent")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalLong;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPresent")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/OptionalLong;"),
-                    options.itemFactory.createProto(options.itemFactory.longType),
-                    options.itemFactory.createString("getAsLong")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/OptionalLong;"),
+                    factory.createProto(factory.longType),
+                    factory.createString("getAsLong")),
                 false),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/LongStream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/LongStream;"),
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("of")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/LongStream;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/stream/LongStream;"), factory.longType),
+                    factory.createString("of")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label2,
@@ -8049,15 +7750,14 @@
                     new int[] {0},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/OptionalLong;"))
+                          factory.createType("Ljava/util/OptionalLong;"))
                     })),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/LongStream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/LongStream;")),
-                    options.itemFactory.createString("empty")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/LongStream;"),
+                    factory.createProto(factory.createType("Ljava/util/stream/LongStream;")),
+                    factory.createString("empty")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label3),
@@ -8065,7 +7765,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode PredicateMethods_not(InternalOptions options, DexMethod method) {
+  public static CfCode PredicateMethods_not(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -8077,11 +7777,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/function/Predicate;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/function/Predicate;")),
-                    options.itemFactory.createString("negate")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/function/Predicate;"),
+                    factory.createProto(factory.createType("Ljava/util/function/Predicate;")),
+                    factory.createString("negate")),
                 true),
             new CfReturn(ValueType.OBJECT),
             label1),
@@ -8089,7 +7788,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ShortMethods_compare(InternalOptions options, DexMethod method) {
+  public static CfCode ShortMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -8107,7 +7806,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ShortMethods_compareUnsigned(InternalOptions options, DexMethod method) {
+  public static CfCode ShortMethods_compareUnsigned(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -8129,7 +7828,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ShortMethods_toUnsignedInt(InternalOptions options, DexMethod method) {
+  public static CfCode ShortMethods_toUnsignedInt(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -8147,7 +7846,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ShortMethods_toUnsignedLong(InternalOptions options, DexMethod method) {
+  public static CfCode ShortMethods_toUnsignedLong(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -8166,7 +7865,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StreamMethods_ofNullable(InternalOptions options, DexMethod method) {
+  public static CfCode StreamMethods_ofNullable(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8181,48 +7880,42 @@
             new CfIf(If.Type.NE, ValueType.OBJECT, label1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;")),
-                    options.itemFactory.createString("empty")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/Stream;"),
+                    factory.createProto(factory.createType("Ljava/util/stream/Stream;")),
+                    factory.createString("empty")),
                 true),
             new CfGoto(label2),
             label1,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)})),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/stream/Stream;"),
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("of")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/stream/Stream;"),
+                    factory.createProto(
+                        factory.createType("Ljava/util/stream/Stream;"), factory.objectType),
+                    factory.createString("of")),
                 true),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    }),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)}),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType("Ljava/util/stream/Stream;"))))),
+                            factory.createType("Ljava/util/stream/Stream;"))))),
             new CfReturn(ValueType.OBJECT),
             label3),
         ImmutableList.of(),
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_isBlank(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_isBlank(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8245,10 +7938,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
             label2,
@@ -8256,7 +7949,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -8268,22 +7961,20 @@
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("codePointAt")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("codePointAt")),
                 false),
             new CfStore(ValueType.INT, 3),
             label4,
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.intType),
-                    options.itemFactory.createString("isWhitespace")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.booleanType, factory.intType),
+                    factory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label6),
             label5,
@@ -8294,7 +7985,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -8303,11 +7994,10 @@
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("charCount")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfStore(ValueType.INT, 1),
@@ -8317,9 +8007,7 @@
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.stringType)})),
             new CfConstNumber(1, ValueType.INT),
             new CfReturn(ValueType.INT),
             label9),
@@ -8327,7 +8015,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_joinArray(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_joinArray(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8347,16 +8035,15 @@
             label0,
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label1),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfConstString(options.itemFactory.createString("delimiter")),
+            new CfConstString(factory.createString("delimiter")),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label1,
@@ -8364,18 +8051,18 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/CharSequence;"))
+                          factory.createType("[Ljava/lang/CharSequence;"))
                     })),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
             label2,
@@ -8389,12 +8076,10 @@
             new CfArrayLoad(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType,
-                        options.itemFactory.charSequenceType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charSequenceType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label4,
@@ -8405,10 +8090,10 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/CharSequence;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType),
+                          factory.createType("[Ljava/lang/CharSequence;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.INT, 3),
@@ -8420,12 +8105,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType,
-                        options.itemFactory.charSequenceType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charSequenceType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label7,
@@ -8435,12 +8118,10 @@
             new CfArrayLoad(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType,
-                        options.itemFactory.charSequenceType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charSequenceType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label8,
@@ -8451,18 +8132,18 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/CharSequence;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType)
+                          factory.createType("[Ljava/lang/CharSequence;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType)
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label10),
@@ -8470,7 +8151,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_joinIterable(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_joinIterable(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8489,16 +8170,15 @@
             label0,
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.NE, ValueType.OBJECT, label1),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfConstString(options.itemFactory.createString("delimiter")),
+            new CfConstString(factory.createString("delimiter")),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label1,
@@ -8506,39 +8186,38 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Iterable;"))
+                          factory.createType("Ljava/lang/Iterable;"))
                     })),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
             label2,
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/Iterable;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/util/Iterator;")),
-                    options.itemFactory.createString("iterator")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Iterable;"),
+                    factory.createProto(factory.createType("Ljava/util/Iterator;")),
+                    factory.createString("iterator")),
                 true),
             new CfStore(ValueType.OBJECT, 3),
             label3,
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("hasNext")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
             label4,
@@ -8546,20 +8225,18 @@
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("next")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("next")),
                 true),
-            new CfCheckCast(options.itemFactory.charSequenceType),
+            new CfCheckCast(factory.charSequenceType),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType,
-                        options.itemFactory.charSequenceType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charSequenceType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label5,
@@ -8567,20 +8244,20 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Iterable;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType),
+                          factory.createType("Ljava/lang/Iterable;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Iterator;"))
+                          factory.createType("Ljava/util/Iterator;"))
                     })),
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.booleanType),
-                    options.itemFactory.createString("hasNext")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.booleanType),
+                    factory.createString("hasNext")),
                 true),
             new CfIf(If.Type.EQ, ValueType.INT, label8),
             label6,
@@ -8588,12 +8265,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType,
-                        options.itemFactory.charSequenceType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charSequenceType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label7,
@@ -8601,20 +8276,18 @@
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 185,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Iterator;"),
-                    options.itemFactory.createProto(options.itemFactory.objectType),
-                    options.itemFactory.createString("next")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Iterator;"),
+                    factory.createProto(factory.objectType),
+                    factory.createString("next")),
                 true),
-            new CfCheckCast(options.itemFactory.charSequenceType),
+            new CfCheckCast(factory.charSequenceType),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType,
-                        options.itemFactory.charSequenceType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charSequenceType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             new CfGoto(label5),
@@ -8623,20 +8296,20 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.charSequenceType),
+                      FrameType.initializedNonNullReference(factory.charSequenceType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/lang/Iterable;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType),
+                          factory.createType("Ljava/lang/Iterable;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Ljava/util/Iterator;"))
+                          factory.createType("Ljava/util/Iterator;"))
                     })),
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label9),
@@ -8644,7 +8317,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_repeat(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_repeat(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8671,49 +8344,46 @@
             new CfLoad(ValueType.INT, 1),
             new CfIf(If.Type.GE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+            new CfNew(factory.createType("Ljava/lang/IllegalArgumentException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("count is negative: ")),
+            new CfConstString(factory.createString("count is negative: ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IllegalArgumentException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -8721,16 +8391,15 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
-                      FrameType.intType()
+                      FrameType.initializedNonNullReference(factory.stringType), FrameType.intType()
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
             label3,
@@ -8743,18 +8412,18 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
-            new CfConstString(options.itemFactory.createString("")),
+            new CfConstString(factory.createString("")),
             new CfReturn(ValueType.OBJECT),
             label5,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -8769,103 +8438,96 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfConstNumber(2147483647, ValueType.INT),
             new CfLoad(ValueType.INT, 1),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Div, NumericType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label10),
             label8,
-            new CfNew(options.itemFactory.createType("Ljava/lang/OutOfMemoryError;")),
+            new CfNew(factory.createType("Ljava/lang/OutOfMemoryError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
-            new CfConstString(options.itemFactory.createString("Repeating ")),
+            new CfConstString(factory.createString("Repeating ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 0),
             label9,
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString(" bytes String ")),
+            new CfConstString(factory.createString(" bytes String ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.intType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.intType),
+                    factory.createString("append")),
                 false),
             new CfConstString(
-                options.itemFactory.createString(
-                    " times will produce a String exceeding maximum size.")),
+                factory.createString(" times will produce a String exceeding maximum size.")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/OutOfMemoryError;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/OutOfMemoryError;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label10,
@@ -8873,22 +8535,21 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.INT, 2),
             new CfLoad(ValueType.INT, 1),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.INT),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.intType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType, factory.intType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 3),
             label11,
@@ -8899,10 +8560,10 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.INT, 4),
@@ -8913,11 +8574,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label14,
@@ -8928,18 +8588,18 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType)
+                      FrameType.initializedNonNullReference(factory.stringBuilderType)
                     })),
             new CfLoad(ValueType.OBJECT, 3),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label16),
@@ -8947,7 +8607,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_strip(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_strip(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -8976,10 +8636,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
             label2,
@@ -8987,7 +8647,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -8999,22 +8659,20 @@
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("codePointAt")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("codePointAt")),
                 false),
             new CfStore(ValueType.INT, 3),
             label4,
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.intType),
-                    options.itemFactory.createString("isWhitespace")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.booleanType, factory.intType),
+                    factory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label6),
             label5,
@@ -9024,7 +8682,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -9033,11 +8691,10 @@
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("charCount")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfStore(ValueType.INT, 1),
@@ -9048,7 +8705,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -9060,24 +8717,20 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("codePointBefore")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.charSequenceType, factory.intType),
+                    factory.createString("codePointBefore")),
                 false),
             new CfStore(ValueType.INT, 3),
             label10,
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.intType),
-                    options.itemFactory.createString("isWhitespace")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.booleanType, factory.intType),
+                    factory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label12),
             label11,
@@ -9087,7 +8740,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -9096,11 +8749,10 @@
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("charCount")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
             new CfStore(ValueType.INT, 2),
@@ -9111,7 +8763,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -9120,13 +8772,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("substring")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.intType, factory.intType),
+                    factory.createString("substring")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label15),
@@ -9134,7 +8783,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_stripLeading(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_stripLeading(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -9157,10 +8806,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 2),
             label2,
@@ -9168,7 +8817,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -9180,22 +8829,20 @@
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("codePointAt")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("codePointAt")),
                 false),
             new CfStore(ValueType.INT, 3),
             label4,
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.intType),
-                    options.itemFactory.createString("isWhitespace")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.booleanType, factory.intType),
+                    factory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label6),
             label5,
@@ -9205,7 +8852,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2, 3},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType(),
                       FrameType.intType()
@@ -9214,11 +8861,10 @@
             new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("charCount")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfStore(ValueType.INT, 1),
@@ -9229,7 +8875,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -9238,13 +8884,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("substring")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.intType, factory.intType),
+                    factory.createString("substring")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label9),
@@ -9252,7 +8895,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode StringMethods_stripTrailing(InternalOptions options, DexMethod method) {
+  public static CfCode StringMethods_stripTrailing(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -9271,10 +8914,10 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfStore(ValueType.INT, 1),
             label1,
@@ -9282,8 +8925,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
-                      FrameType.intType()
+                      FrameType.initializedNonNullReference(factory.stringType), FrameType.intType()
                     })),
             new CfLoad(ValueType.INT, 1),
             new CfIf(If.Type.LE, ValueType.INT, label7),
@@ -9292,24 +8934,20 @@
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.charSequenceType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("codePointBefore")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.charSequenceType, factory.intType),
+                    factory.createString("codePointBefore")),
                 false),
             new CfStore(ValueType.INT, 2),
             label3,
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType, options.itemFactory.intType),
-                    options.itemFactory.createString("isWhitespace")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.booleanType, factory.intType),
+                    factory.createString("isWhitespace")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label5),
             label4,
@@ -9319,7 +8957,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1, 2},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.intType(),
                       FrameType.intType()
                     })),
@@ -9327,11 +8965,10 @@
             new CfLoad(ValueType.INT, 2),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.boxedCharType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType, options.itemFactory.intType),
-                    options.itemFactory.createString("charCount")),
+                factory.createMethod(
+                    factory.boxedCharType,
+                    factory.createProto(factory.intType, factory.intType),
+                    factory.createString("charCount")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
             new CfStore(ValueType.INT, 1),
@@ -9342,21 +8979,17 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
-                      FrameType.intType()
+                      FrameType.initializedNonNullReference(factory.stringType), FrameType.intType()
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfConstNumber(0, ValueType.INT),
             new CfLoad(ValueType.INT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringType,
-                        options.itemFactory.intType,
-                        options.itemFactory.intType),
-                    options.itemFactory.createString("substring")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.stringType, factory.intType, factory.intType),
+                    factory.createString("substring")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label8),
@@ -9364,7 +8997,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode ThrowableMethods_addSuppressed(InternalOptions options, DexMethod method) {
+  public static CfCode ThrowableMethods_addSuppressed(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -9377,43 +9010,43 @@
         3,
         ImmutableList.of(
             label0,
-            new CfConstClass(options.itemFactory.throwableType),
-            new CfConstString(options.itemFactory.createString("addSuppressed")),
+            new CfConstClass(factory.throwableType),
+            new CfConstString(factory.createString("addSuppressed")),
             new CfConstNumber(1, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Class;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Class;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstNumber(0, ValueType.INT),
-            new CfConstClass(options.itemFactory.throwableType),
+            new CfConstClass(factory.throwableType),
             new CfArrayStore(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.classType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                        options.itemFactory.stringType,
-                        options.itemFactory.createType("[Ljava/lang/Class;")),
-                    options.itemFactory.createString("getDeclaredMethod")),
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(
+                        factory.createType("Ljava/lang/reflect/Method;"),
+                        factory.stringType,
+                        factory.createType("[Ljava/lang/Class;")),
+                    factory.createString("getDeclaredMethod")),
                 false),
             new CfStore(ValueType.OBJECT, 2),
             label1,
             new CfLoad(ValueType.OBJECT, 2),
             new CfLoad(ValueType.OBJECT, 0),
             new CfConstNumber(1, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Object;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstNumber(0, ValueType.INT),
             new CfLoad(ValueType.OBJECT, 1),
             new CfArrayStore(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
-                    options.itemFactory.createString("invoke")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/reflect/Method;"),
+                    factory.createProto(
+                        factory.objectType,
+                        factory.objectType,
+                        factory.createType("[Ljava/lang/Object;")),
+                    factory.createString("invoke")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label2,
@@ -9423,21 +9056,21 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.throwableType)
                     }),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType("Ljava/lang/Exception;"))))),
+                            factory.createType("Ljava/lang/Exception;"))))),
             new CfStore(ValueType.OBJECT, 2),
             label4,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType),
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType)
+                      FrameType.initializedNonNullReference(factory.throwableType),
+                      FrameType.initializedNonNullReference(factory.throwableType)
                     })),
             new CfReturnVoid(),
             label5),
@@ -9445,12 +9078,12 @@
             new CfTryCatch(
                 label0,
                 label2,
-                ImmutableList.of(options.itemFactory.createType("Ljava/lang/Exception;")),
+                ImmutableList.of(factory.createType("Ljava/lang/Exception;")),
                 ImmutableList.of(label3))),
         ImmutableList.of());
   }
 
-  public static CfCode ThrowableMethods_getSuppressed(InternalOptions options, DexMethod method) {
+  public static CfCode ThrowableMethods_getSuppressed(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -9463,67 +9096,65 @@
         2,
         ImmutableList.of(
             label0,
-            new CfConstClass(options.itemFactory.throwableType),
-            new CfConstString(options.itemFactory.createString("getSuppressed")),
+            new CfConstClass(factory.throwableType),
+            new CfConstString(factory.createString("getSuppressed")),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Class;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Class;")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.classType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                        options.itemFactory.stringType,
-                        options.itemFactory.createType("[Ljava/lang/Class;")),
-                    options.itemFactory.createString("getDeclaredMethod")),
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(
+                        factory.createType("Ljava/lang/reflect/Method;"),
+                        factory.stringType,
+                        factory.createType("[Ljava/lang/Class;")),
+                    factory.createString("getDeclaredMethod")),
                 false),
             new CfStore(ValueType.OBJECT, 1),
             label1,
             new CfLoad(ValueType.OBJECT, 1),
             new CfLoad(ValueType.OBJECT, 0),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Object;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Object;")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/reflect/Method;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
-                    options.itemFactory.createString("invoke")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/reflect/Method;"),
+                    factory.createProto(
+                        factory.objectType,
+                        factory.objectType,
+                        factory.createType("[Ljava/lang/Object;")),
+                    factory.createString("invoke")),
                 false),
-            new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Throwable;")),
+            new CfCheckCast(factory.createType("[Ljava/lang/Throwable;")),
             label2,
             new CfReturn(ValueType.OBJECT),
             label3,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.throwableType)
-                    }),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.throwableType)}),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType("Ljava/lang/Exception;"))))),
+                            factory.createType("Ljava/lang/Exception;"))))),
             new CfStore(ValueType.OBJECT, 1),
             label4,
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/Throwable;")),
+            new CfNewArray(factory.createType("[Ljava/lang/Throwable;")),
             new CfReturn(ValueType.OBJECT),
             label5),
         ImmutableList.of(
             new CfTryCatch(
                 label0,
                 label2,
-                ImmutableList.of(options.itemFactory.createType("Ljava/lang/Exception;")),
+                ImmutableList.of(factory.createType("Ljava/lang/Exception;")),
                 ImmutableList.of(label3))),
         ImmutableList.of());
   }
 
   public static CfCode UnsafeMethods_compareAndSwapObject(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -9540,12 +9171,12 @@
                     new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Lsun/misc/Unsafe;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                          factory.createType("Lsun/misc/Unsafe;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.longType(),
                       FrameType.longHighType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
@@ -9554,15 +9185,15 @@
             new CfLoad(ValueType.OBJECT, 5),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Lsun/misc/Unsafe;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.booleanType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.longType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType),
-                    options.itemFactory.createString("compareAndSwapObject")),
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(
+                        factory.booleanType,
+                        factory.objectType,
+                        factory.longType,
+                        factory.objectType,
+                        factory.objectType),
+                    factory.createString("compareAndSwapObject")),
                 false),
             new CfIf(If.Type.EQ, ValueType.INT, label2),
             label1,
@@ -9574,25 +9205,22 @@
                     new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("Lsun/misc/Unsafe;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
+                          factory.createType("Lsun/misc/Unsafe;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
                       FrameType.longType(),
                       FrameType.longHighType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType),
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.objectType)
                     })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 1),
             new CfLoad(ValueType.LONG, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Lsun/misc/Unsafe;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.objectType,
-                        options.itemFactory.objectType,
-                        options.itemFactory.longType),
-                    options.itemFactory.createString("getObject")),
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObject")),
                 false),
             new CfLoad(ValueType.OBJECT, 4),
             new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label0),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
index cd385e8..f6b6ac3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
@@ -14,11 +14,11 @@
 import com.android.tools.r8.cf.code.CfStackInstruction;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.MemberType;
 import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
 import org.objectweb.asm.Opcodes;
@@ -27,20 +27,19 @@
 
   private CollectionMethodGenerators() {}
 
-  public static CfCode generateListOf(InternalOptions options, DexMethod method, int formalCount) {
-    return generateFixedMethods(options, method, formalCount, options.itemFactory.listType);
+  public static CfCode generateListOf(DexItemFactory factory, DexMethod method, int formalCount) {
+    return generateFixedMethods(factory, method, formalCount, factory.listType);
   }
 
-  public static CfCode generateSetOf(InternalOptions options, DexMethod method, int formalCount) {
-    return generateFixedMethods(options, method, formalCount, options.itemFactory.setType);
+  public static CfCode generateSetOf(DexItemFactory factory, DexMethod method, int formalCount) {
+    return generateFixedMethods(factory, method, formalCount, factory.setType);
   }
 
   private static CfCode generateFixedMethods(
-      InternalOptions options, DexMethod method, int formalCount, DexType returnType) {
+      DexItemFactory factory, DexMethod method, int formalCount, DexType returnType) {
     Builder<CfInstruction> builder = ImmutableList.builder();
     builder.add(
-        new CfConstNumber(formalCount, ValueType.INT),
-        new CfNewArray(options.itemFactory.objectArrayType));
+        new CfConstNumber(formalCount, ValueType.INT), new CfNewArray(factory.objectArrayType));
 
     for (int i = 0; i < formalCount; i++) {
       builder.add(
@@ -53,28 +52,24 @@
     builder.add(
         new CfInvoke(
             Opcodes.INVOKESTATIC,
-            options.itemFactory.createMethod(
+            factory.createMethod(
                 returnType,
-                options.itemFactory.createProto(returnType, options.itemFactory.objectArrayType),
-                options.itemFactory.createString("of")),
+                factory.createProto(returnType, factory.objectArrayType),
+                factory.createString("of")),
             false),
         new CfReturn(ValueType.OBJECT));
 
     return new CfCode(method.holder, 4, formalCount, builder.build());
   }
 
-  public static CfCode generateMapOf(
-      InternalOptions options, DexMethod method, int formalCount) {
-    DexType mapEntryArray =
-        options.itemFactory.createArrayType(1, options.itemFactory.mapEntryType);
-    DexType simpleEntry = options.itemFactory.abstractMapSimpleEntryType;
-    DexMethod simpleEntryConstructor = options.itemFactory.createMethod(
-        simpleEntry,
-        options.itemFactory.createProto(
-            options.itemFactory.voidType,
-            options.itemFactory.objectType,
-            options.itemFactory.objectType),
-        Constants.INSTANCE_INITIALIZER_NAME);
+  public static CfCode generateMapOf(DexItemFactory factory, DexMethod method, int formalCount) {
+    DexType mapEntryArray = factory.createArrayType(1, factory.mapEntryType);
+    DexType simpleEntry = factory.abstractMapSimpleEntryType;
+    DexMethod simpleEntryConstructor =
+        factory.createMethod(
+            simpleEntry,
+            factory.createProto(factory.voidType, factory.objectType, factory.objectType),
+            Constants.INSTANCE_INITIALIZER_NAME);
 
     Builder<CfInstruction> builder = ImmutableList.builder();
     builder.add(
@@ -96,12 +91,10 @@
     builder.add(
         new CfInvoke(
             Opcodes.INVOKESTATIC,
-            options.itemFactory.createMethod(
-                options.itemFactory.mapType,
-                options.itemFactory.createProto(
-                    options.itemFactory.mapType,
-                    mapEntryArray),
-                options.itemFactory.createString("ofEntries")),
+            factory.createMethod(
+                factory.mapType,
+                factory.createProto(factory.mapType, mapEntryArray),
+                factory.createString("ofEntries")),
             false),
         new CfReturn(ValueType.OBJECT));
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
index 92bd91e..f83ab04 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
@@ -99,7 +99,6 @@
         DexEncodedMethod.syntheticBuilder()
             .setMethod(method)
             .setAccessFlags(methodAccessFlags)
-            .setCode(null)
             .setApiLevelForDefinition(minAPILevel)
             .build();
     libClass.getMethodCollection().addMethod(encodedMethod);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordCfMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordCfMethods.java
index d3955b6..accc84e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordCfMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordCfMethods.java
@@ -34,7 +34,6 @@
 import com.android.tools.r8.ir.code.MemberType;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
 import java.util.ArrayDeque;
@@ -48,7 +47,7 @@
     factory.createSynthesizedType("[Ljava/lang/String;");
   }
 
-  public static CfCode RecordMethods_hashCode(InternalOptions options, DexMethod method) {
+  public static CfCode RecordMethods_hashCode(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -61,21 +60,19 @@
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 184,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/util/Arrays;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.intType,
-                        options.itemFactory.createType("[Ljava/lang/Object;")),
-                    options.itemFactory.createString("hashCode")),
+                factory.createMethod(
+                    factory.createType("Ljava/util/Arrays;"),
+                    factory.createProto(factory.intType, factory.createType("[Ljava/lang/Object;")),
+                    factory.createString("hashCode")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.INT),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("hashCode")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.intType),
+                    factory.createString("hashCode")),
                 false),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfReturn(ValueType.INT),
@@ -84,7 +81,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode RecordMethods_toString(InternalOptions options, DexMethod method) {
+  public static CfCode RecordMethods_toString(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -108,14 +105,14 @@
             new CfLoad(ValueType.OBJECT, 2),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(factory.intType),
+                    factory.createString("length")),
                 false),
             new CfIf(If.Type.NE, ValueType.INT, label1),
             new CfConstNumber(0, ValueType.INT),
-            new CfNewArray(options.itemFactory.createType("[Ljava/lang/String;")),
+            new CfNewArray(factory.createType("[Ljava/lang/String;")),
             new CfGoto(label2),
             label1,
             new CfFrame(
@@ -123,20 +120,19 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.classType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
+                          factory.createType("[Ljava/lang/Object;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(factory.stringType)
                     })),
             new CfLoad(ValueType.OBJECT, 2),
-            new CfConstString(options.itemFactory.createString(";")),
+            new CfConstString(factory.createString(";")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.createType("[Ljava/lang/String;"),
-                        options.itemFactory.stringType),
-                    options.itemFactory.createString("split")),
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(
+                        factory.createType("[Ljava/lang/String;"), factory.stringType),
+                    factory.createString("split")),
                 false),
             label2,
             new CfFrame(
@@ -144,24 +140,24 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.classType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
+                          factory.createType("[Ljava/lang/Object;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(factory.stringType)
                     }),
                 new ArrayDeque<>(
                     Arrays.asList(
                         FrameType.initializedNonNullReference(
-                            options.itemFactory.createType("[Ljava/lang/String;"))))),
+                            factory.createType("[Ljava/lang/String;"))))),
             new CfStore(ValueType.OBJECT, 3),
             label3,
-            new CfNew(options.itemFactory.stringBuilderType),
+            new CfNew(factory.stringBuilderType),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfStore(ValueType.OBJECT, 4),
             label4,
@@ -169,27 +165,25 @@
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.classType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("getSimpleName")),
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("getSimpleName")),
                 false),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString("[")),
+            new CfConstString(factory.createString("[")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label5,
@@ -201,12 +195,12 @@
                     new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.classType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                          factory.createType("[Ljava/lang/Object;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/String;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType),
+                          factory.createType("[Ljava/lang/String;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.INT, 5),
@@ -220,31 +214,28 @@
             new CfArrayLoad(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
-            new CfConstString(options.itemFactory.createString("=")),
+            new CfConstString(factory.createString("=")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.INT, 5),
             new CfArrayLoad(MemberType.OBJECT),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.objectType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.objectType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label8,
@@ -256,14 +247,13 @@
             new CfIfCmp(If.Type.EQ, ValueType.INT, label10),
             label9,
             new CfLoad(ValueType.OBJECT, 4),
-            new CfConstString(options.itemFactory.createString(", ")),
+            new CfConstString(factory.createString(", ")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label10,
@@ -272,12 +262,12 @@
                     new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.classType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                          factory.createType("[Ljava/lang/Object;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/String;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType),
+                          factory.createType("[Ljava/lang/String;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType),
                       FrameType.intType()
                     })),
             new CfIinc(5, 1),
@@ -288,32 +278,31 @@
                     new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/Object;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.classType),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType),
+                          factory.createType("[Ljava/lang/Object;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(factory.stringType),
                       FrameType.initializedNonNullReference(
-                          options.itemFactory.createType("[Ljava/lang/String;")),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringBuilderType)
+                          factory.createType("[Ljava/lang/String;")),
+                      FrameType.initializedNonNullReference(factory.stringBuilderType)
                     })),
             new CfLoad(ValueType.OBJECT, 4),
-            new CfConstString(options.itemFactory.createString("]")),
+            new CfConstString(factory.createString("]")),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(
-                        options.itemFactory.stringBuilderType, options.itemFactory.stringType),
-                    options.itemFactory.createString("append")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label12,
             new CfLoad(ValueType.OBJECT, 4),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringBuilderType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfReturn(ValueType.OBJECT),
             label13),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
index f0ec7b2..81736ab 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
@@ -54,7 +54,6 @@
 import com.android.tools.r8.ir.synthetic.RecordCfCodeProvider.RecordEqualsCfCodeProvider;
 import com.android.tools.r8.ir.synthetic.RecordCfCodeProvider.RecordGetFieldsAsObjectsCfCodeProvider;
 import com.android.tools.r8.ir.synthetic.SyntheticCfCodeProvider;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -240,7 +239,6 @@
         DexEncodedMethod.syntheticBuilder()
             .setMethod(method)
             .setAccessFlags(methodAccessFlags)
-            .setCode(null)
             // Will be traced by the enqueuer.
             .disableAndroidApiLevelCheck()
             .build();
@@ -285,7 +283,7 @@
 
   private ProgramMethod synthesizeRecordHelper(
       DexProto helperProto,
-      BiFunction<InternalOptions, DexMethod, CfCode> codeGenerator,
+      BiFunction<DexItemFactory, DexMethod, CfCode> codeGenerator,
       MethodProcessingContext methodProcessingContext) {
     return appView
         .getSyntheticItems()
@@ -297,7 +295,7 @@
                 builder
                     .setProto(helperProto)
                     .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
-                    .setCode(methodSig -> codeGenerator.apply(appView.options(), methodSig))
+                    .setCode(methodSig -> codeGenerator.apply(appView.dexItemFactory(), methodSig))
                     .disableAndroidApiLevelCheck());
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
index 017ba89..7a9423b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
@@ -23,7 +23,6 @@
 import com.android.tools.r8.ir.desugar.LocalStackAllocator;
 import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
 import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import java.util.function.BiConsumer;
@@ -122,7 +121,7 @@
   private ImmutableList<CfInstruction> createAndCallSyntheticMethod(
       SyntheticKindSelector kindSelector,
       DexProto proto,
-      BiFunction<InternalOptions, DexMethod, CfCode> generator,
+      BiFunction<DexItemFactory, DexMethod, CfCode> generator,
       MethodProcessingContext methodProcessingContext,
       BiConsumer<ProgramMethod, ProgramMethod> eventConsumerCallback,
       ProgramMethod context) {
@@ -139,7 +138,8 @@
                         .disableAndroidApiLevelCheck()
                         .setProto(proto)
                         .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
-                        .setCode(methodSig -> generator.apply(appView.options(), methodSig)));
+                        .setCode(
+                            methodSig -> generator.apply(appView.dexItemFactory(), methodSig)));
     eventConsumerCallback.accept(method, context);
     return ImmutableList.of(new CfInvoke(Opcodes.INVOKESTATIC, method.getReference(), false));
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
index 33e5159..d4d8601 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.optimize.templates.CfUtilityMethodsForCodeOptimizations;
 import com.android.tools.r8.synthesis.SyntheticItems;
-import com.android.tools.r8.utils.InternalOptions;
 
 public class UtilityMethodsForCodeOptimizations {
 
@@ -29,7 +28,6 @@
 
   public static UtilityMethodForCodeOptimizations synthesizeToStringIfNotNullMethod(
       AppView<?> appView, MethodProcessingContext methodProcessingContext) {
-    InternalOptions options = appView.options();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.objectType);
     SyntheticItems syntheticItems = appView.getSyntheticItems();
@@ -44,20 +42,19 @@
                     .setClassFileVersion(CfVersion.V1_8)
                     .setApiLevelForDefinition(appView.computedMinApiLevel())
                     .setApiLevelForCode(appView.computedMinApiLevel())
-                    .setCode(method -> getToStringIfNotNullCodeTemplate(method, options))
+                    .setCode(method -> getToStringIfNotNullCodeTemplate(method, dexItemFactory))
                     .setProto(proto));
     return new UtilityMethodForCodeOptimizations(syntheticMethod);
   }
 
   private static CfCode getToStringIfNotNullCodeTemplate(
-      DexMethod method, InternalOptions options) {
+      DexMethod method, DexItemFactory dexItemFactory) {
     return CfUtilityMethodsForCodeOptimizations
-        .CfUtilityMethodsForCodeOptimizationsTemplates_toStringIfNotNull(options, method);
+        .CfUtilityMethodsForCodeOptimizationsTemplates_toStringIfNotNull(dexItemFactory, method);
   }
 
   public static UtilityMethodForCodeOptimizations synthesizeThrowClassCastExceptionIfNotNullMethod(
       AppView<?> appView, MethodProcessingContext methodProcessingContext) {
-    InternalOptions options = appView.options();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.objectType);
     SyntheticItems syntheticItems = appView.getSyntheticItems();
@@ -74,21 +71,21 @@
                     .setApiLevelForDefinition(appView.computedMinApiLevel())
                     .setApiLevelForCode(appView.computedMinApiLevel())
                     .setCode(
-                        method -> getThrowClassCastExceptionIfNotNullCodeTemplate(method, options))
+                        method ->
+                            getThrowClassCastExceptionIfNotNullCodeTemplate(method, dexItemFactory))
                     .setProto(proto));
     return new UtilityMethodForCodeOptimizations(syntheticMethod);
   }
 
   private static CfCode getThrowClassCastExceptionIfNotNullCodeTemplate(
-      DexMethod method, InternalOptions options) {
+      DexMethod method, DexItemFactory dexItemFactory) {
     return CfUtilityMethodsForCodeOptimizations
         .CfUtilityMethodsForCodeOptimizationsTemplates_throwClassCastExceptionIfNotNull(
-            options, method);
+            dexItemFactory, method);
   }
 
   public static UtilityMethodForCodeOptimizations synthesizeThrowIllegalAccessErrorMethod(
       AppView<?> appView, MethodProcessingContext methodProcessingContext) {
-    InternalOptions options = appView.options();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     DexProto proto = dexItemFactory.createProto(dexItemFactory.illegalAccessErrorType);
     SyntheticItems syntheticItems = appView.getSyntheticItems();
@@ -103,20 +100,21 @@
                     .setClassFileVersion(CfVersion.V1_8)
                     .setApiLevelForDefinition(appView.computedMinApiLevel())
                     .setApiLevelForCode(appView.computedMinApiLevel())
-                    .setCode(method -> getThrowIllegalAccessErrorCodeTemplate(method, options))
+                    .setCode(
+                        method -> getThrowIllegalAccessErrorCodeTemplate(method, dexItemFactory))
                     .setProto(proto));
     return new UtilityMethodForCodeOptimizations(syntheticMethod);
   }
 
   private static CfCode getThrowIllegalAccessErrorCodeTemplate(
-      DexMethod method, InternalOptions options) {
+      DexMethod method, DexItemFactory dexItemFactory) {
     return CfUtilityMethodsForCodeOptimizations
-        .CfUtilityMethodsForCodeOptimizationsTemplates_throwIllegalAccessError(options, method);
+        .CfUtilityMethodsForCodeOptimizationsTemplates_throwIllegalAccessError(
+            dexItemFactory, method);
   }
 
   public static UtilityMethodForCodeOptimizations synthesizeThrowIncompatibleClassChangeErrorMethod(
       AppView<?> appView, MethodProcessingContext methodProcessingContext) {
-    InternalOptions options = appView.options();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     DexProto proto = dexItemFactory.createProto(dexItemFactory.icceType);
     SyntheticItems syntheticItems = appView.getSyntheticItems();
@@ -132,21 +130,22 @@
                     .setApiLevelForDefinition(appView.computedMinApiLevel())
                     .setApiLevelForCode(appView.computedMinApiLevel())
                     .setCode(
-                        method -> getThrowIncompatibleClassChangeErrorCodeTemplate(method, options))
+                        method ->
+                            getThrowIncompatibleClassChangeErrorCodeTemplate(
+                                method, dexItemFactory))
                     .setProto(proto));
     return new UtilityMethodForCodeOptimizations(syntheticMethod);
   }
 
   private static CfCode getThrowIncompatibleClassChangeErrorCodeTemplate(
-      DexMethod method, InternalOptions options) {
+      DexMethod method, DexItemFactory dexItemFactory) {
     return CfUtilityMethodsForCodeOptimizations
         .CfUtilityMethodsForCodeOptimizationsTemplates_throwIncompatibleClassChangeError(
-            options, method);
+            dexItemFactory, method);
   }
 
   public static UtilityMethodForCodeOptimizations synthesizeThrowNoSuchMethodErrorMethod(
       AppView<?> appView, MethodProcessingContext methodProcessingContext) {
-    InternalOptions options = appView.options();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     DexProto proto = dexItemFactory.createProto(dexItemFactory.noSuchMethodErrorType);
     SyntheticItems syntheticItems = appView.getSyntheticItems();
@@ -161,20 +160,21 @@
                     .setClassFileVersion(CfVersion.V1_8)
                     .setApiLevelForDefinition(appView.computedMinApiLevel())
                     .setApiLevelForCode(appView.computedMinApiLevel())
-                    .setCode(method -> getThrowNoSuchMethodErrorCodeTemplate(method, options))
+                    .setCode(
+                        method -> getThrowNoSuchMethodErrorCodeTemplate(method, dexItemFactory))
                     .setProto(proto));
     return new UtilityMethodForCodeOptimizations(syntheticMethod);
   }
 
   private static CfCode getThrowNoSuchMethodErrorCodeTemplate(
-      DexMethod method, InternalOptions options) {
+      DexMethod method, DexItemFactory dexItemFactory) {
     return CfUtilityMethodsForCodeOptimizations
-        .CfUtilityMethodsForCodeOptimizationsTemplates_throwNoSuchMethodError(options, method);
+        .CfUtilityMethodsForCodeOptimizationsTemplates_throwNoSuchMethodError(
+            dexItemFactory, method);
   }
 
   public static UtilityMethodForCodeOptimizations synthesizeThrowRuntimeExceptionWithMessageMethod(
       AppView<?> appView, MethodProcessingContext methodProcessingContext) {
-    InternalOptions options = appView.options();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     DexProto proto =
         dexItemFactory.createProto(dexItemFactory.runtimeExceptionType, dexItemFactory.stringType);
@@ -191,16 +191,17 @@
                     .setApiLevelForDefinition(appView.computedMinApiLevel())
                     .setApiLevelForCode(appView.computedMinApiLevel())
                     .setCode(
-                        method -> getThrowRuntimeExceptionWithMessageCodeTemplate(method, options))
+                        method ->
+                            getThrowRuntimeExceptionWithMessageCodeTemplate(method, dexItemFactory))
                     .setProto(proto));
     return new UtilityMethodForCodeOptimizations(syntheticMethod);
   }
 
   private static CfCode getThrowRuntimeExceptionWithMessageCodeTemplate(
-      DexMethod method, InternalOptions options) {
+      DexMethod method, DexItemFactory dexItemFactory) {
     return CfUtilityMethodsForCodeOptimizations
         .CfUtilityMethodsForCodeOptimizationsTemplates_throwRuntimeExceptionWithMessage(
-            options, method);
+            dexItemFactory, method);
   }
 
   public static class UtilityMethodForCodeOptimizations {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java
index 3a20e47..8ab61f6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java
@@ -35,7 +35,6 @@
 import com.android.tools.r8.ir.code.MemberType;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
 import java.util.ArrayDeque;
@@ -47,7 +46,7 @@
     factory.createSynthesizedType("Ljava/lang/NullPointerException;");
   }
 
-  public static CfCode EnumUnboxingMethods_compareTo(InternalOptions options, DexMethod method) {
+  public static CfCode EnumUnboxingMethods_compareTo(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -66,14 +65,14 @@
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1}, new FrameType[] {FrameType.intType(), FrameType.intType()})),
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -89,7 +88,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode EnumUnboxingMethods_equals(InternalOptions options, DexMethod method) {
+  public static CfCode EnumUnboxingMethods_equals(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -105,14 +104,14 @@
             new CfLoad(ValueType.INT, 0),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -140,7 +139,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode EnumUnboxingMethods_ordinal(InternalOptions options, DexMethod method) {
+  public static CfCode EnumUnboxingMethods_ordinal(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -154,14 +153,14 @@
             new CfLoad(ValueType.INT, 0),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -176,7 +175,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode EnumUnboxingMethods_values(InternalOptions options, DexMethod method) {
+  public static CfCode EnumUnboxingMethods_values(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -191,7 +190,7 @@
         ImmutableList.of(
             label0,
             new CfLoad(ValueType.INT, 0),
-            new CfNewArray(options.itemFactory.intArrayType),
+            new CfNewArray(factory.intArrayType),
             new CfStore(ValueType.OBJECT, 1),
             label1,
             new CfConstNumber(0, ValueType.INT),
@@ -202,7 +201,7 @@
                     new int[] {0, 1, 2},
                     new FrameType[] {
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.intArrayType),
+                      FrameType.initializedNonNullReference(factory.intArrayType),
                       FrameType.intType()
                     })),
             new CfLoad(ValueType.INT, 2),
@@ -225,7 +224,7 @@
                     new int[] {0, 1},
                     new FrameType[] {
                       FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.intArrayType)
+                      FrameType.initializedNonNullReference(factory.intArrayType)
                     })),
             new CfLoad(ValueType.OBJECT, 1),
             new CfReturn(ValueType.OBJECT),
@@ -234,7 +233,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode EnumUnboxingMethods_zeroCheck(InternalOptions options, DexMethod method) {
+  public static CfCode EnumUnboxingMethods_zeroCheck(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -248,14 +247,14 @@
             new CfLoad(ValueType.INT, 0),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -268,7 +267,7 @@
   }
 
   public static CfCode EnumUnboxingMethods_zeroCheckMessage(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -282,16 +281,15 @@
             new CfLoad(ValueType.INT, 0),
             new CfIf(If.Type.NE, ValueType.INT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+            new CfNew(factory.createType("Ljava/lang/NullPointerException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 1),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NullPointerException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NullPointerException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
@@ -299,8 +297,7 @@
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0, 1},
                     new FrameType[] {
-                      FrameType.intType(),
-                      FrameType.initializedNonNullReference(options.itemFactory.stringType)
+                      FrameType.intType(), FrameType.initializedNonNullReference(factory.stringType)
                     })),
             new CfReturnVoid(),
             label3),
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
index 5edfe2e..c24a972 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
@@ -81,7 +81,7 @@
         appView,
         dexItemFactory.createString("checkNotZero"),
         dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.intType),
-        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheck(appView.options(), method));
+        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheck(dexItemFactory, method));
   }
 
   public ProgramMethod ensureCheckNotZeroWithMessageMethod(AppView<AppInfoWithLiveness> appView) {
@@ -92,7 +92,7 @@
         dexItemFactory.createProto(
             dexItemFactory.voidType, dexItemFactory.intType, dexItemFactory.stringType),
         method ->
-            EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheckMessage(appView.options(), method));
+            EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheckMessage(dexItemFactory, method));
   }
 
   public ProgramMethod ensureCompareToMethod(AppView<AppInfoWithLiveness> appView) {
@@ -102,7 +102,7 @@
         dexItemFactory.enumMembers.compareTo.getName(),
         dexItemFactory.createProto(
             dexItemFactory.intType, dexItemFactory.intType, dexItemFactory.intType),
-        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_compareTo(appView.options(), method));
+        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_compareTo(dexItemFactory, method));
   }
 
   public ProgramMethod ensureEqualsMethod(AppView<AppInfoWithLiveness> appView) {
@@ -112,7 +112,7 @@
         dexItemFactory.enumMembers.equals.getName(),
         dexItemFactory.createProto(
             dexItemFactory.booleanType, dexItemFactory.intType, dexItemFactory.intType),
-        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_equals(appView.options(), method));
+        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_equals(dexItemFactory, method));
   }
 
   public ProgramMethod ensureOrdinalMethod(AppView<AppInfoWithLiveness> appView) {
@@ -121,7 +121,7 @@
         appView,
         dexItemFactory.enumMembers.ordinalMethod.getName(),
         dexItemFactory.createProto(dexItemFactory.intType, dexItemFactory.intType),
-        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_ordinal(appView.options(), method));
+        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_ordinal(dexItemFactory, method));
   }
 
   private ProgramMethod internalEnsureMethod(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/templates/CfUtilityMethodsForCodeOptimizations.java b/src/main/java/com/android/tools/r8/ir/optimize/templates/CfUtilityMethodsForCodeOptimizations.java
index d512ff4..f06beb7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/templates/CfUtilityMethodsForCodeOptimizations.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/templates/CfUtilityMethodsForCodeOptimizations.java
@@ -23,7 +23,6 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.ir.code.If;
 import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
 
@@ -39,7 +38,7 @@
 
   public static CfCode
       CfUtilityMethodsForCodeOptimizationsTemplates_throwClassCastExceptionIfNotNull(
-          InternalOptions options, DexMethod method) {
+          DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -53,23 +52,21 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfIf(If.Type.EQ, ValueType.OBJECT, label2),
             label1,
-            new CfNew(options.itemFactory.createType("Ljava/lang/ClassCastException;")),
+            new CfNew(factory.createType("Ljava/lang/ClassCastException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/ClassCastException;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/ClassCastException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)})),
             new CfReturnVoid(),
             label3),
         ImmutableList.of(),
@@ -77,7 +74,7 @@
   }
 
   public static CfCode CfUtilityMethodsForCodeOptimizationsTemplates_throwIllegalAccessError(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     return new CfCode(
         method.holder,
@@ -85,14 +82,14 @@
         0,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IllegalAccessError;")),
+            new CfNew(factory.createType("Ljava/lang/IllegalAccessError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IllegalAccessError;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IllegalAccessError;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow()),
         ImmutableList.of(),
@@ -101,7 +98,7 @@
 
   public static CfCode
       CfUtilityMethodsForCodeOptimizationsTemplates_throwIncompatibleClassChangeError(
-          InternalOptions options, DexMethod method) {
+          DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     return new CfCode(
         method.holder,
@@ -109,14 +106,14 @@
         0,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/lang/IncompatibleClassChangeError;")),
+            new CfNew(factory.createType("Ljava/lang/IncompatibleClassChangeError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/IncompatibleClassChangeError;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/IncompatibleClassChangeError;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow()),
         ImmutableList.of(),
@@ -124,7 +121,7 @@
   }
 
   public static CfCode CfUtilityMethodsForCodeOptimizationsTemplates_throwNoSuchMethodError(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     return new CfCode(
         method.holder,
@@ -132,14 +129,14 @@
         0,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/lang/NoSuchMethodError;")),
+            new CfNew(factory.createType("Ljava/lang/NoSuchMethodError;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/NoSuchMethodError;"),
-                    options.itemFactory.createProto(options.itemFactory.voidType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/NoSuchMethodError;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow()),
         ImmutableList.of(),
@@ -148,7 +145,7 @@
 
   public static CfCode
       CfUtilityMethodsForCodeOptimizationsTemplates_throwRuntimeExceptionWithMessage(
-          InternalOptions options, DexMethod method) {
+          DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     return new CfCode(
@@ -157,16 +154,15 @@
         1,
         ImmutableList.of(
             label0,
-            new CfNew(options.itemFactory.createType("Ljava/lang/RuntimeException;")),
+            new CfNew(factory.createType("Ljava/lang/RuntimeException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 183,
-                options.itemFactory.createMethod(
-                    options.itemFactory.createType("Ljava/lang/RuntimeException;"),
-                    options.itemFactory.createProto(
-                        options.itemFactory.voidType, options.itemFactory.stringType),
-                    options.itemFactory.createString("<init>")),
+                factory.createMethod(
+                    factory.createType("Ljava/lang/RuntimeException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
                 false),
             new CfThrow(),
             label1),
@@ -175,7 +171,7 @@
   }
 
   public static CfCode CfUtilityMethodsForCodeOptimizationsTemplates_toStringIfNotNull(
-      InternalOptions options, DexMethod method) {
+      DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
     CfLabel label2 = new CfLabel();
@@ -192,19 +188,17 @@
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
                 182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.objectType,
-                    options.itemFactory.createProto(options.itemFactory.stringType),
-                    options.itemFactory.createString("toString")),
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
                 false),
             new CfStackInstruction(CfStackInstruction.Opcode.Pop),
             label2,
             new CfFrame(
                 new Int2ObjectAVLTreeMap<>(
                     new int[] {0},
-                    new FrameType[] {
-                      FrameType.initializedNonNullReference(options.itemFactory.objectType)
-                    })),
+                    new FrameType[] {FrameType.initializedNonNullReference(factory.objectType)})),
             new CfReturnVoid(),
             label3),
         ImmutableList.of(),
diff --git a/src/main/java/com/android/tools/r8/references/Reference.java b/src/main/java/com/android/tools/r8/references/Reference.java
index 75dfb4c..d5071d2 100644
--- a/src/main/java/com/android/tools/r8/references/Reference.java
+++ b/src/main/java/com/android/tools/r8/references/Reference.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableList;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.Collections;
@@ -119,6 +120,16 @@
         holderClass, methodName, ImmutableList.copyOf(formalTypes), returnType);
   }
 
+  /** Get a method reference from a Java reflection executable. */
+  public static MethodReference methodFromMethod(Executable executable) {
+    if (executable instanceof Constructor<?>) {
+      return methodFromMethod((Constructor<?>) executable);
+    } else {
+      assert executable instanceof Method;
+      return methodFromMethod((Method) executable);
+    }
+  }
+
   /** Get a method reference from a Java reflection method. */
   public static MethodReference methodFromMethod(Method method) {
     String methodName = method.getName();
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java
index ff09bd7..973a89d 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java
@@ -112,18 +112,6 @@
     return captureGroupIndex;
   }
 
-  private boolean isTypeOrBinarySeparator(String regularExpression, int startIndex, int endIndex) {
-    assert endIndex < regularExpression.length();
-    if (startIndex + 1 != endIndex) {
-      return false;
-    }
-    if (regularExpression.charAt(startIndex) != '\\') {
-      return false;
-    }
-    return regularExpression.charAt(startIndex + 1) == '.'
-        || regularExpression.charAt(startIndex + 1) == '/';
-  }
-
   private RegularExpressionGroup getGroupFromVariable(char variable) {
     switch (variable) {
       case 'c':
@@ -274,16 +262,12 @@
 
   private static class SourceFileGroup extends RegularExpressionGroup {
 
-    static String subExpressionInternal() {
-      String anyNonDigitNonColonNonWhitespaceChar = "^\\d:\\s";
-      String anyNonColonChar = "^:";
-      String colonWithNonDigitSuffix = ":+[" + anyNonDigitNonColonNonWhitespaceChar + "]";
-      return "((?:(?:(?:" + colonWithNonDigitSuffix + "))|(?:[" + anyNonColonChar + "]))+)?";
-    }
-
     @Override
     String subExpression() {
-      return subExpressionInternal();
+      String anyNonDigitNonColonCharNonWhiteSpace = "[^\\d:\\s]";
+      String anyNonColonChar = "[^:]";
+      String colonsWithNonDigitOrWhiteSpaceSuffix = ":+" + anyNonDigitNonColonCharNonWhiteSpace;
+      return "(?:" + colonsWithNonDigitOrWhiteSpaceSuffix + "|" + anyNonColonChar + "*)*";
     }
 
     @Override
@@ -323,7 +307,7 @@
 
     @Override
     String subExpression() {
-      return SourceFileGroup.subExpressionInternal() + "(?::\\d*)?";
+      return ".*";
     }
 
     @Override
@@ -333,8 +317,8 @@
         if (startOfGroup == NO_MATCH) {
           return false;
         }
-        int endOfSourceFineInGroup = findEndOfSourceFile(matcher.group(captureGroup));
-        int sourceFileEnd = startOfGroup + endOfSourceFineInGroup;
+        int endOfSourceFileInGroup = findEndOfSourceFile(matcher.group(captureGroup));
+        int sourceFileEnd = startOfGroup + endOfSourceFileInGroup;
         builder.registerSourceFile(startOfGroup, sourceFileEnd);
         int endOfMatch = matcher.end(captureGroup);
         int lineNumberStart = sourceFileEnd + 1;
diff --git a/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java
new file mode 100644
index 0000000..cbbfc33
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java
@@ -0,0 +1,163 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ***********************************************************************************
+// GENERATED FILE. DO NOT EDIT! See InstrumentationServerClassGenerator.java.
+// ***********************************************************************************
+
+package com.android.tools.r8.startup.generated;
+
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
+import com.android.tools.r8.cf.CfVersion;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfLoad;
+import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.EnclosingMethodAttribute;
+import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
+import com.android.tools.r8.graph.NestHostClassAttribute;
+import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.origin.Origin;
+import com.google.common.collect.ImmutableList;
+import java.util.Collections;
+
+public final class InstrumentationServerFactory {
+  public static DexProgramClass createClass(DexItemFactory dexItemFactory) {
+    return new DexProgramClass(
+        dexItemFactory.createType(
+            "Lcom/android/tools/r8/startup/generated/InstrumentationServerFactory;"),
+        Kind.CF,
+        Origin.unknown(),
+        ClassAccessFlags.fromCfAccessFlags(1025),
+        null,
+        DexTypeList.empty(),
+        dexItemFactory.createString("InstrumentationServerFactory"),
+        NestHostClassAttribute.none(),
+        Collections.emptyList(),
+        Collections.emptyList(),
+        EnclosingMethodAttribute.none(),
+        Collections.emptyList(),
+        ClassSignature.noSignature(),
+        DexAnnotationSet.empty(),
+        createStaticFields(dexItemFactory),
+        createInstanceFields(dexItemFactory),
+        MethodCollectionFactory.fromMethods(
+            createDirectMethods(dexItemFactory), createVirtualMethods(dexItemFactory)),
+        dexItemFactory.getSkipNameValidationForTesting(),
+        DexProgramClass::invalidChecksumRequest);
+  }
+
+  private static DexEncodedField[] createInstanceFields(DexItemFactory dexItemFactory) {
+    return new DexEncodedField[] {};
+  }
+
+  private static DexEncodedField[] createStaticFields(DexItemFactory dexItemFactory) {
+    return new DexEncodedField[] {};
+  }
+
+  private static DexEncodedMethod[] createDirectMethods(DexItemFactory dexItemFactory) {
+    return new DexEncodedMethod[] {
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(9, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType("Lcom/android/tools/r8/startup/InstrumentationServer;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType(
+                          "Lcom/android/tools/r8/startup/InstrumentationServer;")),
+                  dexItemFactory.createString("getInstance")))
+          .setCode(method -> createCfCode1_getInstance(dexItemFactory, method))
+          .build()
+    };
+  }
+
+  private static DexEncodedMethod[] createVirtualMethods(DexItemFactory dexItemFactory) {
+    return new DexEncodedMethod[] {
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(1, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createInstanceInitializer(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServer;")))
+          .setCode(method -> createInstanceInitializerCfCode0(dexItemFactory, method))
+          .build(),
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(1025, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType("Lcom/android/tools/r8/startup/InstrumentationServer;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType("V"), dexItemFactory.createType("Ljava/io/File;")),
+                  dexItemFactory.createString("writeToFile")))
+          .build()
+    };
+  }
+
+  public static CfCode createInstanceInitializerCfCode0(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        1,
+        1,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfReturnVoid(),
+            label1),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode1_getInstance(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        1,
+        0,
+        ImmutableList.of(
+            label0,
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createProto(
+                        factory.createType(
+                            "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+                    factory.createString("getInstance")),
+                false),
+            new CfReturn(ValueType.OBJECT)),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java
new file mode 100644
index 0000000..f0c8f9b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java
@@ -0,0 +1,637 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ***********************************************************************************
+// GENERATED FILE. DO NOT EDIT! See InstrumentationServerClassGenerator.java.
+// ***********************************************************************************
+
+package com.android.tools.r8.startup.generated;
+
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
+import com.android.tools.r8.cf.CfVersion;
+import com.android.tools.r8.cf.code.CfConstNumber;
+import com.android.tools.r8.cf.code.CfConstString;
+import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfGoto;
+import com.android.tools.r8.cf.code.CfInstanceFieldRead;
+import com.android.tools.r8.cf.code.CfInstanceFieldWrite;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfLoad;
+import com.android.tools.r8.cf.code.CfNew;
+import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStaticFieldRead;
+import com.android.tools.r8.cf.code.CfStaticFieldWrite;
+import com.android.tools.r8.cf.code.CfStore;
+import com.android.tools.r8.cf.code.CfThrow;
+import com.android.tools.r8.cf.code.CfTryCatch;
+import com.android.tools.r8.cf.code.frame.FrameType;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.EnclosingMethodAttribute;
+import com.android.tools.r8.graph.FieldAccessFlags;
+import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
+import com.android.tools.r8.graph.NestHostClassAttribute;
+import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.origin.Origin;
+import com.google.common.collect.ImmutableList;
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Collections;
+
+public final class InstrumentationServerImplFactory {
+  public static DexProgramClass createClass(DexItemFactory dexItemFactory) {
+    return new DexProgramClass(
+        dexItemFactory.createType(
+            "Lcom/android/tools/r8/startup/generated/InstrumentationServerImplFactory;"),
+        Kind.CF,
+        Origin.unknown(),
+        ClassAccessFlags.fromCfAccessFlags(1),
+        null,
+        DexTypeList.empty(),
+        dexItemFactory.createString("InstrumentationServerImplFactory"),
+        NestHostClassAttribute.none(),
+        Collections.emptyList(),
+        Collections.emptyList(),
+        EnclosingMethodAttribute.none(),
+        Collections.emptyList(),
+        ClassSignature.noSignature(),
+        DexAnnotationSet.empty(),
+        createStaticFields(dexItemFactory),
+        createInstanceFields(dexItemFactory),
+        MethodCollectionFactory.fromMethods(
+            createDirectMethods(dexItemFactory), createVirtualMethods(dexItemFactory)),
+        dexItemFactory.getSkipNameValidationForTesting(),
+        DexProgramClass::invalidChecksumRequest);
+  }
+
+  private static DexEncodedField[] createInstanceFields(DexItemFactory dexItemFactory) {
+    return new DexEncodedField[] {
+      DexEncodedField.syntheticBuilder()
+          .setField(
+              dexItemFactory.createField(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createType("Ljava/lang/StringBuilder;"),
+                  dexItemFactory.createString("builder")))
+          .setAccessFlags(FieldAccessFlags.fromCfAccessFlags(18))
+          .setApiLevel(ComputedApiLevel.unknown())
+          .build(),
+      DexEncodedField.syntheticBuilder()
+          .setField(
+              dexItemFactory.createField(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createType("Ljava/lang/String;"),
+                  dexItemFactory.createString("logcatTag")))
+          .setAccessFlags(FieldAccessFlags.fromCfAccessFlags(18))
+          .setApiLevel(ComputedApiLevel.unknown())
+          .build(),
+      DexEncodedField.syntheticBuilder()
+          .setField(
+              dexItemFactory.createField(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createType("Z"),
+                  dexItemFactory.createString("writeToLogcat")))
+          .setAccessFlags(FieldAccessFlags.fromCfAccessFlags(18))
+          .setApiLevel(ComputedApiLevel.unknown())
+          .build()
+    };
+  }
+
+  private static DexEncodedField[] createStaticFields(DexItemFactory dexItemFactory) {
+    return new DexEncodedField[] {
+      DexEncodedField.syntheticBuilder()
+          .setField(
+              dexItemFactory.createField(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createString("INSTANCE")))
+          .setAccessFlags(FieldAccessFlags.fromCfAccessFlags(26))
+          .setApiLevel(ComputedApiLevel.unknown())
+          .build()
+    };
+  }
+
+  private static DexEncodedMethod[] createDirectMethods(DexItemFactory dexItemFactory) {
+    return new DexEncodedMethod[] {
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(2, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createInstanceInitializer(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")))
+          .setCode(method -> createInstanceInitializerCfCode1(dexItemFactory, method))
+          .build(),
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(34, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType("V"),
+                      dexItemFactory.createType("Ljava/lang/String;")),
+                  dexItemFactory.createString("addLine")))
+          .setCode(method -> createCfCode2_addLine(dexItemFactory, method))
+          .build(),
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(9, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType("V"),
+                      dexItemFactory.createType("Ljava/lang/String;")),
+                  dexItemFactory.createString("addNonSyntheticMethod")))
+          .setCode(method -> createCfCode3_addNonSyntheticMethod(dexItemFactory, method))
+          .build(),
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(9, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType("V"),
+                      dexItemFactory.createType("Ljava/lang/String;")),
+                  dexItemFactory.createString("addSyntheticMethod")))
+          .setCode(method -> createCfCode4_addSyntheticMethod(dexItemFactory, method))
+          .build(),
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(9, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType(
+                          "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+                  dexItemFactory.createString("getInstance")))
+          .setCode(method -> createCfCode5_getInstance(dexItemFactory, method))
+          .build(),
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(2, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType("V"),
+                      dexItemFactory.createType("Ljava/lang/String;")),
+                  dexItemFactory.createString("writeToLogcat")))
+          .setCode(method -> createCfCode7_writeToLogcat(dexItemFactory, method))
+          .build()
+    };
+  }
+
+  private static DexEncodedMethod[] createVirtualMethods(DexItemFactory dexItemFactory) {
+    return new DexEncodedMethod[] {
+      DexEncodedMethod.syntheticBuilder()
+          .setAccessFlags(MethodAccessFlags.fromCfAccessFlags(33, false))
+          .setApiLevelForCode(ComputedApiLevel.unknown())
+          .setApiLevelForDefinition(ComputedApiLevel.unknown())
+          .setClassFileVersion(CfVersion.V1_8)
+          .setMethod(
+              dexItemFactory.createMethod(
+                  dexItemFactory.createType(
+                      "Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                  dexItemFactory.createProto(
+                      dexItemFactory.createType("V"), dexItemFactory.createType("Ljava/io/File;")),
+                  dexItemFactory.createString("writeToFile")))
+          .setCode(method -> createCfCode6_writeToFile(dexItemFactory, method))
+          .build()
+    };
+  }
+
+  public static CfCode createClassInitializerCfCode(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        2,
+        0,
+        ImmutableList.of(
+            label0,
+            new CfNew(
+                factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfStaticFieldWrite(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createString("INSTANCE"))),
+            new CfReturnVoid()),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createInstanceInitializerCfCode1(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        1,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServer;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            label1,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfNew(factory.stringBuilderType),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfInstanceFieldWrite(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.stringBuilderType,
+                    factory.createString("builder"))),
+            label2,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfConstNumber(0, ValueType.INT),
+            new CfInstanceFieldWrite(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.booleanType,
+                    factory.createString("writeToLogcat"))),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfConstString(factory.createString("r8")),
+            new CfInstanceFieldWrite(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.stringType,
+                    factory.createString("logcatTag"))),
+            label4,
+            new CfReturnVoid(),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode2_addLine(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        2,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.stringBuilderType,
+                    factory.createString("builder"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfConstNumber(10, ValueType.INT),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charType),
+                    factory.createString("append")),
+                false),
+            new CfStackInstruction(CfStackInstruction.Opcode.Pop),
+            label1,
+            new CfReturnVoid(),
+            label2),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode3_addNonSyntheticMethod(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        2,
+        1,
+        ImmutableList.of(
+            label0,
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createProto(
+                        factory.createType(
+                            "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+                    factory.createString("getInstance")),
+                false),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("addLine")),
+                false),
+            label1,
+            new CfReturnVoid(),
+            label2),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode4_addSyntheticMethod(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        1,
+        ImmutableList.of(
+            label0,
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createProto(
+                        factory.createType(
+                            "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+                    factory.createString("getInstance")),
+                false),
+            new CfNew(factory.stringBuilderType),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfConstNumber(83, ValueType.INT),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.charType),
+                    factory.createString("append")),
+                false),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
+                false),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("addLine")),
+                false),
+            label1,
+            new CfReturnVoid(),
+            label2),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode5_getInstance(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        1,
+        0,
+        ImmutableList.of(
+            label0,
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.createString("INSTANCE"))),
+            new CfReturn(ValueType.OBJECT)),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode6_writeToFile(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    CfLabel label6 = new CfLabel();
+    CfLabel label7 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        4,
+        ImmutableList.of(
+            label0,
+            new CfNew(factory.createType("Ljava/io/FileOutputStream;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/io/FileOutputStream;"),
+                    factory.createProto(factory.voidType, factory.createType("Ljava/io/File;")),
+                    factory.createString("<init>")),
+                false),
+            new CfStore(ValueType.OBJECT, 2),
+            label1,
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Lcom/android/tools/r8/startup/InstrumentationServerImpl;"),
+                    factory.stringBuilderType,
+                    factory.createString("builder"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
+                false),
+            new CfConstString(factory.createString("UTF-8")),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/nio/charset/Charset;"),
+                    factory.createProto(
+                        factory.createType("Ljava/nio/charset/Charset;"), factory.stringType),
+                    factory.createString("forName")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringType,
+                    factory.createProto(
+                        factory.byteArrayType, factory.createType("Ljava/nio/charset/Charset;")),
+                    factory.createString("getBytes")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/io/FileOutputStream;"),
+                    factory.createProto(factory.voidType, factory.byteArrayType),
+                    factory.createString("write")),
+                false),
+            label2,
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/io/FileOutputStream;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("close")),
+                false),
+            label3,
+            new CfGoto(label6),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType(
+                              "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+                      FrameType.initializedNonNullReference(factory.createType("Ljava/io/File;")),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/io/FileOutputStream;"))
+                    }),
+                new ArrayDeque<>(
+                    Arrays.asList(FrameType.initializedNonNullReference(factory.throwableType)))),
+            new CfStore(ValueType.OBJECT, 3),
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/io/FileOutputStream;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("close")),
+                false),
+            label5,
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfThrow(),
+            label6,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType(
+                              "Lcom/android/tools/r8/startup/InstrumentationServerImpl;")),
+                      FrameType.initializedNonNullReference(factory.createType("Ljava/io/File;")),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/io/FileOutputStream;"))
+                    })),
+            new CfReturnVoid(),
+            label7),
+        ImmutableList.of(
+            new CfTryCatch(
+                label1, label2, ImmutableList.of(factory.throwableType), ImmutableList.of(label4))),
+        ImmutableList.of());
+  }
+
+  public static CfCode createCfCode7_writeToLogcat(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        2,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfConstString(factory.createString("r8")),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Landroid/util/Log;"),
+                    factory.createProto(factory.intType, factory.stringType, factory.stringType),
+                    factory.createString("v")),
+                false),
+            new CfStackInstruction(CfStackInstruction.Opcode.Pop),
+            label1,
+            new CfReturnVoid(),
+            label2),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
index 17b3673..3c2605a 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
@@ -250,7 +250,7 @@
         }
       };
     } catch (NoSuchMethodException e) {
-      e.printStackTrace();
+      System.out.println(setter + " is not available on the compiledump version.");
       // The option is not available so we just return an empty consumer
       return args -> {};
     }
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 7d6d982..78547de 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -397,6 +397,9 @@
   // Boolean value indicating that byte code pass through may be enabled.
   public boolean enableCfByteCodePassThrough = false;
 
+  // TODO(b/238175192): remove again when resolved
+  public boolean enableUnrepresentableInDexInstructionRemoval = false;
+
   // Flag to control the representation of stateless lambdas.
   // See b/222081665 for context.
   public boolean createSingletonsForStatelessLambdas =
diff --git a/src/test/examplesJava17/lambda/Lambda.java b/src/test/examplesJava17/lambda/Lambda.java
new file mode 100644
index 0000000..d0c1035
--- /dev/null
+++ b/src/test/examplesJava17/lambda/Lambda.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package lambda;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Lambda {
+
+  interface StringPredicate {
+
+    boolean test(String t);
+
+    default StringPredicate or(StringPredicate other) {
+      return (t) -> test(t) || other.test(t);
+    }
+  }
+
+  public static void main(String[] args) {
+    ArrayList<String> strings = new ArrayList<>();
+    strings.add("abc");
+    strings.add("abb");
+    strings.add("bbc");
+    strings.add("aac");
+    strings.add("acc");
+    StringPredicate aaStart = Lambda::aaStart;
+    StringPredicate bbNot = Lambda::bbNot;
+    StringPredicate full = aaStart.or(bbNot);
+    for (String string : ((List<String>) strings.clone())) {
+      if (full.test(string)) {
+        strings.remove(string);
+      }
+    }
+    System.out.println(strings);
+  }
+
+  private static boolean aaStart(String str) {
+    return str.startsWith("aa");
+  }
+
+  private static boolean bbNot(String str) {
+    return !str.contains("bb");
+  }
+}
diff --git a/src/test/examplesJava17/nest/NestLambda.java b/src/test/examplesJava17/nest/NestLambda.java
index 2c690b5..c60a8fb 100644
--- a/src/test/examplesJava17/nest/NestLambda.java
+++ b/src/test/examplesJava17/nest/NestLambda.java
@@ -4,8 +4,6 @@
 
 package nest;
 
-import java.util.function.Consumer;
-
 public class NestLambda {
 
   private void print(Object o) {
@@ -16,9 +14,14 @@
     return new Inner();
   }
 
-  class Inner {
+  // Avoids java.util.Consumer to run below on Apis below 24.
+  interface ThisConsumer<T> {
+    void accept(T t);
+  }
 
-    void exec(Consumer<Object> consumer) {
+  class Inner implements Itf {
+
+    void exec(ThisConsumer<String> consumer) {
       consumer.accept("inner");
     }
 
@@ -27,7 +30,22 @@
     }
   }
 
+  interface Itf {
+    private void printItf(Object o) {
+      System.out.println("printed from itf: " + o);
+    }
+  }
+
+  void exec(ThisConsumer<String> consumer) {
+    consumer.accept("here");
+  }
+
+  void execItfLambda(Itf itf) {
+    exec(itf::printItf);
+  }
+
   public static void main(String[] args) {
     new NestLambda().getInner().execLambda();
+    new NestLambda().execItfLambda(new Itf() {});
   }
 }
diff --git a/src/test/java/android/util/Log.java b/src/test/java/android/util/Log.java
new file mode 100644
index 0000000..2ca06ef
--- /dev/null
+++ b/src/test/java/android/util/Log.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package android.util;
+
+// Partial API of android.util.Log.
+
+public class Log {
+
+  public static int v(String tag, String message) {
+    throw new RuntimeException();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
index 180b043..737e8bd 100644
--- a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
+++ b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -63,10 +63,11 @@
     KOTLINC_1_4_20("kotlin-compiler-1.4.20"),
     KOTLINC_1_5_0("kotlin-compiler-1.5.0"),
     KOTLINC_1_6_0("kotlin-compiler-1.6.0"),
+    KOTLINC_1_7_0("kotlin-compiler-1.7.0"),
     KOTLIN_DEV("kotlin-compiler-dev");
 
-    public static final KotlinCompilerVersion MIN_SUPPORTED_VERSION = KOTLINC_1_4_20;
-    public static final KotlinCompilerVersion MAX_SUPPORTED_VERSION = KOTLINC_1_6_0;
+    public static final KotlinCompilerVersion MIN_SUPPORTED_VERSION = KOTLINC_1_5_0;
+    public static final KotlinCompilerVersion MAX_SUPPORTED_VERSION = KOTLINC_1_7_0;
 
     private final String folder;
 
diff --git a/src/test/java/com/android/tools/r8/cf/methodhandles/InvokeMethodHandleRuntimeErrorTest.java b/src/test/java/com/android/tools/r8/cf/methodhandles/InvokeMethodHandleRuntimeErrorTest.java
index 889fd91..1fcabcd 100644
--- a/src/test/java/com/android/tools/r8/cf/methodhandles/InvokeMethodHandleRuntimeErrorTest.java
+++ b/src/test/java/com/android/tools/r8/cf/methodhandles/InvokeMethodHandleRuntimeErrorTest.java
@@ -67,6 +67,9 @@
         .addProgramClassFileData(getInvokeCustomTransform())
         .setMinApi(parameters.getApiLevel())
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics -> {
               if (hasCompileSupport()) {
diff --git a/src/test/java/com/android/tools/r8/cf/methodhandles/MethodHandleTestRunner.java b/src/test/java/com/android/tools/r8/cf/methodhandles/MethodHandleTestRunner.java
index 1812854..ae44ac9 100644
--- a/src/test/java/com/android/tools/r8/cf/methodhandles/MethodHandleTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/methodhandles/MethodHandleTestRunner.java
@@ -104,6 +104,9 @@
         .addProgramClasses(getInputClasses())
         .addProgramClassFileData(getTransformedClasses())
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), CLASS.getName())
         .apply(this::checkResult);
@@ -117,7 +120,10 @@
             .addProgramClasses(getInputClasses())
             .addProgramClassFileData(getTransformedClasses())
             .addLibraryFiles(ToolHelper.getMostRecentAndroidJar())
-            .addNoVerticalClassMergingAnnotations();
+            .addNoVerticalClassMergingAnnotations()
+            // TODO(b/238175192): remove again when resolved
+            .addOptionsModification(
+                options -> options.enableUnrepresentableInDexInstructionRemoval = true);
     if (minifyMode == MinifyMode.MINIFY) {
       builder
           .enableProguardTestOptions()
diff --git a/src/test/java/com/android/tools/r8/cf/methodhandles/fields/ClassFieldMethodHandleTest.java b/src/test/java/com/android/tools/r8/cf/methodhandles/fields/ClassFieldMethodHandleTest.java
index 062f22e..aac5a20 100644
--- a/src/test/java/com/android/tools/r8/cf/methodhandles/fields/ClassFieldMethodHandleTest.java
+++ b/src/test/java/com/android/tools/r8/cf/methodhandles/fields/ClassFieldMethodHandleTest.java
@@ -73,6 +73,9 @@
         .addProgramClassFileData(getTransformedMain())
         .setMinApi(parameters.getApiLevel())
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), Main.class)
         .apply(this::checkResult);
@@ -88,6 +91,9 @@
         .setMinApi(parameters.getApiLevel())
         .allowDiagnosticMessages()
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), Main.class)
         .apply(this::checkResult);
diff --git a/src/test/java/com/android/tools/r8/cf/methodhandles/fields/InterfaceFieldMethodHandleTest.java b/src/test/java/com/android/tools/r8/cf/methodhandles/fields/InterfaceFieldMethodHandleTest.java
index 3d62b40..629a737 100644
--- a/src/test/java/com/android/tools/r8/cf/methodhandles/fields/InterfaceFieldMethodHandleTest.java
+++ b/src/test/java/com/android/tools/r8/cf/methodhandles/fields/InterfaceFieldMethodHandleTest.java
@@ -76,6 +76,9 @@
         .addProgramClassFileData(getTransformedMain())
         .setMinApi(parameters.getApiLevel())
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), Main.class)
         .apply(this::checkResult);
@@ -91,6 +94,9 @@
         .setMinApi(parameters.getApiLevel())
         .allowDiagnosticMessages()
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), Main.class)
         .apply(this::checkResult);
diff --git a/src/test/java/com/android/tools/r8/cf/methodhandles/invokespecial/InvokeSpecialMethodHandleTest.java b/src/test/java/com/android/tools/r8/cf/methodhandles/invokespecial/InvokeSpecialMethodHandleTest.java
index 459ce08..70d3aec 100644
--- a/src/test/java/com/android/tools/r8/cf/methodhandles/invokespecial/InvokeSpecialMethodHandleTest.java
+++ b/src/test/java/com/android/tools/r8/cf/methodhandles/invokespecial/InvokeSpecialMethodHandleTest.java
@@ -76,6 +76,9 @@
         .addProgramClassFileData(getTransformedD())
         .setMinApi(parameters.getApiLevel())
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), Main.class)
         .apply(this::checkResult);
@@ -91,6 +94,9 @@
         .setMinApi(parameters.getApiLevel())
         .allowDiagnosticMessages()
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(this::checkDiagnostics)
         .run(parameters.getRuntime(), Main.class)
         .apply(this::checkResult);
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/CfClassGenerator.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/CfClassGenerator.java
new file mode 100644
index 0000000..5435248
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/CfClassGenerator.java
@@ -0,0 +1,451 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cfmethodgeneration;
+
+import static com.android.tools.r8.utils.PredicateUtils.not;
+
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.cf.CfCodePrinter;
+import com.android.tools.r8.graph.ClassKind;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.FieldAccessFlags;
+import com.android.tools.r8.graph.JarApplicationReader;
+import com.android.tools.r8.graph.JarClassFileReader;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.FieldReferenceUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.MethodReferenceUtils;
+import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.Streams;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.function.Predicate;
+
+public abstract class CfClassGenerator extends CodeGenerationBase {
+
+  private final CfCodeGeneratorImportCollection imports = new CfCodeGeneratorImportCollection();
+
+  public abstract Class<?> getImplementation();
+
+  public String generateClass() throws IOException {
+    return formatRawOutput(generateRawOutput());
+  }
+
+  private String generateRawOutput() throws IOException {
+    String classDeclaration = generateClassDeclaration();
+    return StringUtils.lines(getHeaderString(), imports.generateImports(), classDeclaration);
+  }
+
+  private String generateClassDeclaration() throws IOException {
+    JavaStringBuilder builder = new JavaStringBuilder();
+    builder.append("public final class " + getGeneratedClassName() + " ").appendOpeningBrace();
+    generateCreateClassMethod(builder);
+    generateCreateFieldsMethod(builder, "createInstanceFields", not(FieldAccessFlags::isStatic));
+    generateCreateFieldsMethod(builder, "createStaticFields", FieldAccessFlags::isStatic);
+    CfCodePrinter codePrinter = new CfCodePrinter();
+    Map<MethodReference, String> createCfCodeMethodNames = generateCreateCfCodeMethods(codePrinter);
+    generateCreateMethodsMethod(
+        builder,
+        "createDirectMethods",
+        MethodAccessFlags::belongsToDirectPool,
+        createCfCodeMethodNames);
+    generateCreateMethodsMethod(
+        builder,
+        "createVirtualMethods",
+        MethodAccessFlags::belongsToVirtualPool,
+        createCfCodeMethodNames);
+    codePrinter.getMethods().forEach(builder::appendLine);
+    builder.appendClosingBrace();
+    return builder.toString();
+  }
+
+  private void generateCreateClassMethod(JavaStringBuilder builder) {
+    builder
+        .startLine()
+        .append("public static ")
+        .append(imports.getDexProgramClass())
+        .append(" createClass(")
+        .append(imports.getDexItemFactory())
+        .append(" dexItemFactory) ")
+        .appendOpeningBrace();
+
+    builder
+        .startLine()
+        .append("return new ")
+        .append(imports.getDexProgramClass())
+        .appendOpeningMultiLineParenthesis();
+
+    builder
+        .startLine()
+        .append("dexItemFactory.createType(\"")
+        .append(getGeneratedClassDescriptor())
+        .appendLine("\"),");
+
+    builder.startLine().append(imports.getProgramResourceKind()).appendLine(".CF,");
+
+    builder.startLine().append(imports.getOrigin()).appendLine(".unknown(),");
+
+    builder
+        .startLine()
+        .append(imports.getClassAccessFlags())
+        .append(".fromCfAccessFlags(")
+        .append(getImplementation().getModifiers())
+        .appendLine("),");
+
+    builder.startLine().appendLine("null,");
+
+    builder.startLine().append(imports.getDexTypeList()).appendLine(".empty(),");
+
+    builder
+        .startLine()
+        .append("dexItemFactory.createString(\"")
+        .append(getGeneratedClassName())
+        .appendLine("\"),");
+
+    builder.startLine().append(imports.getNestHostClassAttribute()).appendLine(".none(),");
+
+    for (int i = 0; i < 2; i++) {
+      builder.startLine().append(imports.getJavaUtilCollections()).appendLine(".emptyList(),");
+    }
+
+    builder.startLine().append(imports.getEnclosingMethodAttribute()).appendLine(".none(),");
+
+    builder.startLine().append(imports.getJavaUtilCollections()).appendLine(".emptyList(),");
+
+    builder.startLine().append(imports.getClassSignature()).appendLine(".noSignature(),");
+
+    builder.startLine().append(imports.getDexAnnotationSet()).appendLine(".empty(),");
+
+    builder.startLine().appendLine("createStaticFields(dexItemFactory),");
+
+    builder.startLine().appendLine("createInstanceFields(dexItemFactory),");
+
+    builder
+        .startLine()
+        .append(imports.getMethodCollectionFactory())
+        .appendLine(
+            ".fromMethods(createDirectMethods(dexItemFactory),"
+                + " createVirtualMethods(dexItemFactory)),");
+
+    builder.startLine().appendLine("dexItemFactory.getSkipNameValidationForTesting(),");
+
+    builder.startLine().append(imports.getDexProgramClass()).append("::invalidChecksumRequest");
+
+    builder.appendClosingMultiLineParenthesis().appendLine(';');
+    builder.appendClosingBrace();
+  }
+
+  private void generateCreateFieldsMethod(
+      JavaStringBuilder builder, String methodName, Predicate<FieldAccessFlags> predicate) {
+    builder
+        .startLine()
+        .append("private static ")
+        .append(imports.getDexEncodedField())
+        .append("[] ")
+        .append(methodName)
+        .append("(")
+        .append(imports.getDexItemFactory())
+        .append(" dexItemFactory) ")
+        .appendOpeningBrace();
+
+    builder
+        .startLine()
+        .append("return new ")
+        .append(imports.getDexEncodedField())
+        .append("[] ")
+        .appendOpeningArrayBrace();
+
+    Iterator<Field> fieldIterator =
+        Arrays.stream(getImplementation().getDeclaredFields())
+            .filter(
+                field -> predicate.test(FieldAccessFlags.fromCfAccessFlags(field.getModifiers())))
+            .sorted(
+                (x, y) ->
+                    FieldReferenceUtils.compare(
+                        Reference.fieldFromField(x), Reference.fieldFromField(y)))
+            .iterator();
+    while (fieldIterator.hasNext()) {
+      Field field = fieldIterator.next();
+      FieldAccessFlags flags = FieldAccessFlags.fromCfAccessFlags(field.getModifiers());
+      if (predicate.test(flags)) {
+        builder
+            .startLine()
+            .append(imports.getDexEncodedField())
+            .appendLine(".syntheticBuilder()")
+            .indent(4);
+
+        builder.startLine().append(".setField").appendOpeningMultiLineParenthesis();
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createField")
+            .appendOpeningMultiLineParenthesis();
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createType(\"")
+            .append(descriptor(field.getDeclaringClass()))
+            .appendLine("\"),");
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createType(\"")
+            .append(descriptor(field.getType()))
+            .appendLine("\"),");
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createString(\"")
+            .append(field.getName())
+            .append("\")")
+            .appendClosingMultiLineParenthesis()
+            .appendClosingMultiLineParenthesis()
+            .appendLine();
+
+        builder
+            .startLine()
+            .append(".setAccessFlags(")
+            .append(imports.getFieldAccessFlags())
+            .append(".fromCfAccessFlags(")
+            .append(field.getModifiers())
+            .appendLine("))");
+
+        builder
+            .startLine()
+            .append(".setApiLevel(")
+            .append(imports.getComputedApiLevel())
+            .appendLine(".unknown())");
+
+        builder.startLine().append(".build()").indent(-4);
+        if (fieldIterator.hasNext()) {
+          builder.appendLine(',');
+        } else {
+          builder.appendLine();
+        }
+      }
+    }
+
+    builder.appendClosingArrayBrace();
+    builder.appendClosingBrace();
+  }
+
+  private void generateCreateMethodsMethod(
+      JavaStringBuilder builder,
+      String methodName,
+      Predicate<MethodAccessFlags> predicate,
+      Map<MethodReference, String> createCfCodeMethodNames) {
+    builder
+        .startLine()
+        .append("private static ")
+        .append(imports.getDexEncodedMethod())
+        .append("[] ")
+        .append(methodName)
+        .append("(")
+        .append(imports.getDexItemFactory())
+        .append(" dexItemFactory) ")
+        .appendOpeningBrace();
+
+    builder
+        .startLine()
+        .append("return new ")
+        .append(imports.getDexEncodedMethod())
+        .append("[] ")
+        .appendOpeningArrayBrace();
+
+    getImplementation().getDeclaredConstructors();
+
+    Iterator<Executable> executableIterator =
+        Streams.concat(
+                Arrays.stream(getImplementation().getDeclaredConstructors()),
+                Arrays.stream(getImplementation().getDeclaredMethods()))
+            .filter(
+                executable ->
+                    predicate.test(
+                        MethodAccessFlags.fromCfAccessFlags(executable.getModifiers(), false)))
+            .sorted(
+                (x, y) ->
+                    MethodReferenceUtils.compare(
+                        Reference.methodFromMethod(x), Reference.methodFromMethod(y)))
+            .iterator();
+    while (executableIterator.hasNext()) {
+      Executable executable = executableIterator.next();
+      builder
+          .startLine()
+          .append(imports.getDexEncodedMethod())
+          .appendLine(".syntheticBuilder()")
+          .indent(4);
+
+      builder
+          .startLine()
+          .append(".setAccessFlags(")
+          .append(imports.getMethodAccessFlags())
+          .append(".fromCfAccessFlags(")
+          .append(executable.getModifiers())
+          .append(", false")
+          .appendLine("))");
+
+      builder
+          .startLine()
+          .append(".setApiLevelForCode(")
+          .append(imports.getComputedApiLevel())
+          .appendLine(".unknown())");
+
+      builder
+          .startLine()
+          .append(".setApiLevelForDefinition(")
+          .append(imports.getComputedApiLevel())
+          .appendLine(".unknown())");
+
+      builder
+          .startLine()
+          .append(".setClassFileVersion(")
+          .append(imports.getCfVersion())
+          .appendLine(".V1_8)");
+
+      builder.startLine().append(".setMethod").appendOpeningMultiLineParenthesis();
+
+      if (executable instanceof Constructor<?>) {
+        Constructor<?> constructor = (Constructor<?>) executable;
+        builder
+            .startLine()
+            .append("dexItemFactory.createInstanceInitializer")
+            .appendOpeningMultiLineParenthesis();
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createType(\"")
+            .append(descriptor(constructor.getDeclaringClass()))
+            .append("\")");
+
+        for (Class<?> parameter : constructor.getParameterTypes()) {
+          builder
+              .appendLine(",")
+              .startLine()
+              .append("dexItemFactory.createType(\"")
+              .append(descriptor(parameter))
+              .append("\")");
+        }
+      } else {
+        assert executable instanceof Method;
+        Method method = (Method) executable;
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createMethod")
+            .appendOpeningMultiLineParenthesis();
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createType(\"")
+            .append(descriptor(method.getDeclaringClass()))
+            .appendLine("\"),");
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createProto")
+            .appendOpeningMultiLineParenthesis();
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createType(\"")
+            .append(descriptor(method.getReturnType()))
+            .append("\")");
+
+        for (Class<?> parameter : method.getParameterTypes()) {
+          builder
+              .appendLine(",")
+              .startLine()
+              .append("dexItemFactory.createType(\"")
+              .append(descriptor(parameter))
+              .append("\")");
+        }
+        builder.appendClosingMultiLineParenthesis().appendLine(',');
+
+        builder
+            .startLine()
+            .append("dexItemFactory.createString(\"")
+            .append(method.getName())
+            .append("\")");
+      }
+
+      builder.appendClosingMultiLineParenthesis().appendClosingMultiLineParenthesis().appendLine();
+
+      String createCfCodeMethodName =
+          createCfCodeMethodNames.get(Reference.methodFromMethod(executable));
+      if (createCfCodeMethodName != null) {
+        builder
+            .startLine()
+            .append(".setCode(method -> ")
+            .append(createCfCodeMethodName)
+            .appendLine("(dexItemFactory, method))");
+      }
+
+      builder.startLine().append(".build()").indent(-4);
+      if (executableIterator.hasNext()) {
+        builder.appendLine(',');
+      } else {
+        builder.appendLine();
+      }
+    }
+
+    builder.appendClosingArrayBrace();
+    builder.appendClosingBrace();
+  }
+
+  private Map<MethodReference, String> generateCreateCfCodeMethods(CfCodePrinter codePrinter)
+      throws IOException {
+    Map<MethodReference, String> createCfCodeMethodNames = new HashMap<>();
+    InternalOptions options = new InternalOptions(factory, new Reporter());
+    options.testing.readInputStackMaps = true;
+    JarClassFileReader<DexProgramClass> reader =
+        new JarClassFileReader<>(
+            new JarApplicationReader(options),
+            clazz -> {
+              int index = 0;
+              for (DexEncodedMethod method : clazz.allMethodsSorted()) {
+                if (!method.hasCode()) {
+                  continue;
+                }
+                String generatedMethodName = getCreateCfCodeMethodName(method, index);
+                createCfCodeMethodNames.put(
+                    method.getReference().asMethodReference(), generatedMethodName);
+                codePrinter.visitMethod(generatedMethodName, method.getCode().asCfCode());
+                index++;
+              }
+            },
+            ClassKind.PROGRAM);
+    reader.read(Origin.unknown(), ToolHelper.getClassAsBytes(getImplementation()));
+    codePrinter.getImports().forEach(imports::addImport);
+    return createCfCodeMethodNames;
+  }
+
+  private String getCreateCfCodeMethodName(DexEncodedMethod method, int index) {
+    if (method.isClassInitializer()) {
+      return "createClassInitializerCfCode";
+    }
+    if (method.isInstanceInitializer()) {
+      return "createInstanceInitializerCfCode" + index;
+    }
+    return "createCfCode" + index + "_" + method.getName().toString();
+  }
+
+  public void writeClassToFile() throws IOException {
+    FileUtils.writeToFile(getGeneratedFile(), null, generateClass().getBytes());
+  }
+}
+
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/CfCodeGeneratorImportCollection.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/CfCodeGeneratorImportCollection.java
new file mode 100644
index 0000000..12be5f6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/CfCodeGeneratorImportCollection.java
@@ -0,0 +1,110 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cfmethodgeneration;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class CfCodeGeneratorImportCollection {
+
+  private final Set<String> imports = new LinkedHashSet<>();
+
+  String generateImports() {
+    StringBuilder builder = new StringBuilder();
+    for (String className : imports) {
+      builder.append("import ").append(className).append(";").append('\n');
+    }
+    return builder.toString();
+  }
+
+  String getCfVersion() {
+    return getR8ClassName("cf", "CfVersion");
+  }
+
+  String getClassAccessFlags() {
+    return getR8ClassName("graph", "ClassAccessFlags");
+  }
+
+  String getClassSignature() {
+    return getR8ClassName("graph.GenericSignature", "ClassSignature");
+  }
+
+  String getComputedApiLevel() {
+    return getR8ClassName("androidapi", "ComputedApiLevel");
+  }
+
+  String getDexAnnotationSet() {
+    return getR8ClassName("graph", "DexAnnotationSet");
+  }
+
+  String getDexEncodedField() {
+    return getR8ClassName("graph", "DexEncodedField");
+  }
+
+  String getDexEncodedMethod() {
+    return getR8ClassName("graph", "DexEncodedMethod");
+  }
+
+  String getDexItemFactory() {
+    return getR8ClassName("graph", "DexItemFactory");
+  }
+
+  String getDexProgramClass() {
+    return getR8ClassName("graph", "DexProgramClass");
+  }
+
+  String getDexTypeList() {
+    return getR8ClassName("graph", "DexTypeList");
+  }
+
+  String getEnclosingMethodAttribute() {
+    return getR8ClassName("graph", "EnclosingMethodAttribute");
+  }
+
+  String getFieldAccessFlags() {
+    return getR8ClassName("graph", "FieldAccessFlags");
+  }
+
+  String getFieldTypeSignature() {
+    return getR8ClassName("graph.GenericSignature", "FieldTypeSignature");
+  }
+
+  String getJavaUtilCollections() {
+    addImport("java.util.Collections");
+    return "Collections";
+  }
+
+  String getMethodAccessFlags() {
+    return getR8ClassName("graph", "MethodAccessFlags");
+  }
+
+  String getMethodCollectionFactory() {
+    return getR8ClassName("graph.MethodCollection", "MethodCollectionFactory");
+  }
+
+  String getNestHostClassAttribute() {
+    return getR8ClassName("graph", "NestHostClassAttribute");
+  }
+
+  String getOrigin() {
+    return getR8ClassName("origin", "Origin");
+  }
+
+  String getProgramResourceKind() {
+    return getR8ClassName("ProgramResource", "Kind");
+  }
+
+  private String getR8ClassName(String context, String name) {
+    String canonicalName =
+        "com.android.tools.r8." + (context != null ? (context + ".") : "") + name;
+    addImport(canonicalName);
+    return name;
+  }
+
+  String addImport(String name) {
+    imports.add(name);
+    return name;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/CodeGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/CodeGenerationBase.java
new file mode 100644
index 0000000..ee1a991
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/CodeGenerationBase.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cfmethodgeneration;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public abstract class CodeGenerationBase extends TestBase {
+
+  private static final Path GOOGLE_FORMAT_DIR =
+      Paths.get(ToolHelper.THIRD_PARTY_DIR, "google-java-format");
+  private static final Path GOOGLE_FORMAT_JAR =
+      GOOGLE_FORMAT_DIR.resolve("google-java-format-1.7-all-deps.jar");
+
+  protected final DexItemFactory factory = new DexItemFactory();
+
+  public static String formatRawOutput(String rawOutput) throws IOException {
+    File temporaryFile = File.createTempFile("output-", ".java");
+    Files.write(temporaryFile.toPath(), rawOutput.getBytes());
+    String result = formatRawOutput(temporaryFile.toPath());
+    temporaryFile.deleteOnExit();
+    return result;
+  }
+
+  public static String formatRawOutput(Path tempFile) throws IOException {
+    // Apply google format.
+    ProcessBuilder builder =
+        new ProcessBuilder(
+            ImmutableList.of(
+                getJavaExecutable(),
+                "-jar",
+                GOOGLE_FORMAT_JAR.toString(),
+                tempFile.toAbsolutePath().toString()));
+    String commandString = String.join(" ", builder.command());
+    System.out.println(commandString);
+    Process process = builder.start();
+    ProcessResult result = ToolHelper.drainProcessOutputStreams(process, commandString);
+    if (result.exitCode != 0) {
+      throw new IllegalStateException(result.toString());
+    }
+    // Fix line separators.
+    String content = result.stdout;
+    if (!StringUtils.LINE_SEPARATOR.equals("\n")) {
+      return content.replace(StringUtils.LINE_SEPARATOR, "\n");
+    }
+    return content;
+  }
+
+  public String getGeneratedClassDescriptor() {
+    return getGeneratedType().toDescriptorString();
+  }
+
+  public String getGeneratedClassName() {
+    return getGeneratedType().getName();
+  }
+
+  public String getGeneratedClassPackageName() {
+    return getGeneratedType().getPackageName();
+  }
+
+  public Path getGeneratedFile() {
+    return Paths.get(ToolHelper.SOURCE_DIR, getGeneratedType().getInternalName() + ".java");
+  }
+
+  protected abstract DexType getGeneratedType();
+
+  public String getHeaderString() {
+    String simpleName = getClass().getSimpleName();
+    return getHeaderString(getYear(), simpleName)
+        + StringUtils.lines("package " + getGeneratedClassPackageName() + ";");
+  }
+
+  public static String getHeaderString(int year, String simpleNameOfGenerator) {
+    return StringUtils.lines(
+        "// Copyright (c) " + year + ", 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.",
+        "",
+        "// ***********************************************************************************",
+        "// GENERATED FILE. DO NOT EDIT! See " + simpleNameOfGenerator + ".java.",
+        "// ***********************************************************************************",
+        "");
+  }
+
+  protected static String getJavaExecutable() {
+    return ToolHelper.getSystemJavaExecutable();
+  }
+
+  protected abstract int getYear();
+}
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/JavaStringBuilder.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/JavaStringBuilder.java
new file mode 100644
index 0000000..7de114a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/JavaStringBuilder.java
@@ -0,0 +1,79 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cfmethodgeneration;
+
+public class JavaStringBuilder {
+
+  private final StringBuilder builder = new StringBuilder();
+  private int indentation = 0;
+
+  public JavaStringBuilder append(char c) {
+    builder.append(c);
+    return this;
+  }
+
+  public JavaStringBuilder append(int i) {
+    builder.append(i);
+    return this;
+  }
+
+  public JavaStringBuilder append(String string) {
+    builder.append(string);
+    return this;
+  }
+
+  public JavaStringBuilder appendLine() {
+    return append('\n');
+  }
+
+  public JavaStringBuilder appendLine(char c) {
+    return append(c).appendLine();
+  }
+
+  public JavaStringBuilder appendLine(String string) {
+    return append(string).appendLine();
+  }
+
+  public JavaStringBuilder appendOpeningBrace() {
+    return appendLine('{').indent(2);
+  }
+
+  public JavaStringBuilder appendClosingBrace() {
+    return indent(-2).startLine().appendLine('}');
+  }
+
+  public JavaStringBuilder appendOpeningArrayBrace() {
+    return appendLine('{').indent(4);
+  }
+
+  public JavaStringBuilder appendClosingArrayBrace() {
+    return indent(-4).startLine().appendLine("};");
+  }
+
+  public JavaStringBuilder appendOpeningMultiLineParenthesis() {
+    return appendLine('(').indent(4);
+  }
+
+  public JavaStringBuilder appendClosingMultiLineParenthesis() {
+    return append(')').indent(-4);
+  }
+
+  public JavaStringBuilder indent(int change) {
+    indentation += change;
+    return this;
+  }
+
+  public JavaStringBuilder startLine() {
+    for (int i = 0; i < indentation; i++) {
+      append(' ');
+    }
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    return builder.toString();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
index 692773c..28ab9a7 100644
--- a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
@@ -4,86 +4,34 @@
 
 package com.android.tools.r8.cfmethodgeneration;
 
-import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.cf.CfCodePrinter;
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.ClassKind;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.JarApplicationReader;
 import com.android.tools.r8.graph.JarClassFileReader;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.StringUtils;
-import com.google.common.collect.ImmutableList;
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.List;
 import java.util.TreeSet;
 
-public abstract class MethodGenerationBase extends TestBase {
-
-  private static final Path GOOGLE_FORMAT_DIR =
-      Paths.get(ToolHelper.THIRD_PARTY_DIR, "google-java-format");
-  private static final Path GOOGLE_FORMAT_JAR =
-      GOOGLE_FORMAT_DIR.resolve("google-java-format-1.7-all-deps.jar");
-
-  protected final DexItemFactory factory = new DexItemFactory();
-
-  protected static String getJavaExecutable() {
-    return ToolHelper.getSystemJavaExecutable();
-  }
-
-  protected abstract DexType getGeneratedType();
+public abstract class MethodGenerationBase extends CodeGenerationBase {
 
   protected abstract List<Class<?>> getMethodTemplateClasses();
 
-  protected abstract int getYear();
-
-  public String getHeaderString() {
-    String simpleName = getClass().getSimpleName();
-    return getHeaderString(getYear(), simpleName)
-        + StringUtils.lines("package " + getGeneratedClassPackageName() + ";");
-  }
-
-  public static String getHeaderString(int year, String simpeNameOfGenerator) {
-    return StringUtils.lines(
-        "// Copyright (c) " + year + ", 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.",
-        "",
-        "// ***********************************************************************************",
-        "// GENERATED FILE. DO NOT EDIT! See " + simpeNameOfGenerator + ".java.",
-        "// ***********************************************************************************",
-        "");
-  }
-
-  protected Path getGeneratedFile() {
-    return Paths.get(ToolHelper.SOURCE_DIR, getGeneratedType().getInternalName() + ".java");
-  }
-
   protected CfCode getCode(String holderName, String methodName, CfCode code) {
     return code;
   }
 
-  private String getGeneratedClassName() {
-    return getGeneratedType().getName();
-  }
-
-  private String getGeneratedClassPackageName() {
-    return getGeneratedType().getPackageName();
-  }
-
   // Running this method will regenerate / overwrite the content of the generated class.
   protected void generateMethodsAndWriteThemToFile() throws IOException {
     FileUtils.writeToFile(getGeneratedFile(), null, generateMethods().getBytes());
@@ -145,28 +93,4 @@
       printer.println("}");
     }
   }
-
-  public static String formatRawOutput(Path tempFile) throws IOException {
-    // Apply google format.
-    ProcessBuilder builder =
-        new ProcessBuilder(
-            ImmutableList.of(
-                getJavaExecutable(),
-                "-jar",
-                GOOGLE_FORMAT_JAR.toString(),
-                tempFile.toAbsolutePath().toString()));
-    String commandString = String.join(" ", builder.command());
-    System.out.println(commandString);
-    Process process = builder.start();
-    ProcessResult result = ToolHelper.drainProcessOutputStreams(process, commandString);
-    if (result.exitCode != 0) {
-      throw new IllegalStateException(result.toString());
-    }
-    // Fix line separators.
-    String content = result.stdout;
-    if (!StringUtils.LINE_SEPARATOR.equals("\n")) {
-      return content.replace(StringUtils.LINE_SEPARATOR, "\n");
-    }
-    return content;
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/code/invokedynamic/CompileGuavaWithUnrepresentableRewritingTest.java b/src/test/java/com/android/tools/r8/code/invokedynamic/CompileGuavaWithUnrepresentableRewritingTest.java
new file mode 100644
index 0000000..655675e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/code/invokedynamic/CompileGuavaWithUnrepresentableRewritingTest.java
@@ -0,0 +1,58 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.code.invokedynamic;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/** This is a regression test for b/238175192 */
+@RunWith(Parameterized.class)
+public class CompileGuavaWithUnrepresentableRewritingTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  @Test
+  public void testD8DexNoDesugaring() throws Throwable {
+    assumeTrue(ToolHelper.isTestingR8Lib());
+    // TODO(b/238175192): We should not generate invalid bytecode
+    assertThrows(
+        CompilationFailedException.class,
+        () -> {
+          testForD8(Backend.DEX)
+              .addProgramFiles(ToolHelper.DEPS)
+              .setMinApi(AndroidApiLevel.B)
+              .disableDesugaring()
+              .mapUnsupportedFeaturesToWarnings()
+              // TODO(b/238175192): remove again when resolved
+              .addOptionsModification(
+                  options -> options.enableUnrepresentableInDexInstructionRemoval = true)
+              .compileWithExpectedDiagnostics(
+                  diagnostics ->
+                      diagnostics
+                          .assertErrorMessageThatMatches(
+                              containsString("Expected stack type to be single width"))
+                          .assertWarningMessageThatMatches(
+                              containsString("Invalid stack map table at instruction")));
+        });
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeCustomRuntimeErrorTest.java b/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeCustomRuntimeErrorTest.java
index cf34d5d..1fa8060 100644
--- a/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeCustomRuntimeErrorTest.java
+++ b/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeCustomRuntimeErrorTest.java
@@ -89,6 +89,9 @@
         .setMinApi(parameters.getApiLevel())
         .disableDesugaring()
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics ->
                 diagnostics
@@ -110,6 +113,8 @@
         .addProgramClassFileData(getTransformedTestClass())
         .setMinApi(minApi)
         .mapUnsupportedFeaturesToWarnings()
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics -> {
               if (expectedSuccess) {
diff --git a/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeDynamicVirtualDispatchToDefaultInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeDynamicVirtualDispatchToDefaultInterfaceMethodTest.java
index 7494b13..c2caab7 100644
--- a/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeDynamicVirtualDispatchToDefaultInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/code/invokedynamic/InvokeDynamicVirtualDispatchToDefaultInterfaceMethodTest.java
@@ -71,6 +71,9 @@
         .addProgramClassFileData(getTransformedTestClass())
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(TestClass.class)
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .addKeepRules("-keepclassmembers class * { *** foo(...); }")
         .run(parameters.getRuntime(), TestClass.class)
         .assertSuccessWithOutput(EXPECTED);
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
index 1a9eff3..419a379 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
@@ -361,6 +361,12 @@
         checkLocal(p_mangledLvName),
         stepInto(),
         // We're out of inlinee2
+        // For kotlin dev (18.alpha) we need an additional step, see b/238067321.
+        applyIf(
+            kotlinParameters
+                .getCompilerVersion()
+                .isGreaterThan(KotlinCompilerVersion.KOTLINC_1_7_0),
+            this::stepInto),
         checkMethod(DEBUGGEE_CLASS, inliningMethodName),
         checkLocal(inlinee1_inlineScope),
         checkNoLocal(inlinee2_inlineScope),
diff --git a/src/test/java/com/android/tools/r8/desugar/constantdynamic/ConstantDynamicHolderTest.java b/src/test/java/com/android/tools/r8/desugar/constantdynamic/ConstantDynamicHolderTest.java
index 8c1d8f1..2dde386 100644
--- a/src/test/java/com/android/tools/r8/desugar/constantdynamic/ConstantDynamicHolderTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/constantdynamic/ConstantDynamicHolderTest.java
@@ -66,6 +66,9 @@
                         || diagnostic instanceof ConstantDynamicDesugarDiagnostic)
                     ? DiagnosticsLevel.WARNING
                     : level)
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics ->
                 diagnostics.assertWarningsMatch(
@@ -105,6 +108,9 @@
         .addKeepMainRule(Main.class)
         .allowDiagnosticWarningMessages()
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics -> {
               if (parameters.isDexRuntime()) {
diff --git a/src/test/java/com/android/tools/r8/desugar/constantdynamic/SharedBootstrapMethodConstantDynamicTest.java b/src/test/java/com/android/tools/r8/desugar/constantdynamic/SharedBootstrapMethodConstantDynamicTest.java
index 87f3382..88328c7 100644
--- a/src/test/java/com/android/tools/r8/desugar/constantdynamic/SharedBootstrapMethodConstantDynamicTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/constantdynamic/SharedBootstrapMethodConstantDynamicTest.java
@@ -90,6 +90,9 @@
                         || diagnostic instanceof UnsupportedFeatureDiagnostic)
                     ? DiagnosticsLevel.WARNING
                     : level)
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics ->
                 diagnostics
@@ -121,6 +124,9 @@
                         || diagnostic instanceof UnsupportedFeatureDiagnostic)
                     ? DiagnosticsLevel.WARNING
                     : level)
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics -> {
               diagnostics.assertOnlyWarnings();
@@ -167,6 +173,9 @@
         .addKeepMainRule(MAIN_CLASS)
         .allowDiagnosticMessages()
         .mapUnsupportedFeaturesToWarnings()
+        // TODO(b/238175192): remove again when resolved
+        .addOptionsModification(
+            options -> options.enableUnrepresentableInDexInstructionRemoval = true)
         .compileWithExpectedDiagnostics(
             diagnostics -> {
               diagnostics
diff --git a/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaJava17Test.java b/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaJava17Test.java
new file mode 100644
index 0000000..6c9e899
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaJava17Test.java
@@ -0,0 +1,79 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.lambdas;
+
+import static com.android.tools.r8.utils.AndroidApiLevel.B;
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class LambdaJava17Test extends TestBase {
+
+  public LambdaJava17Test(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  private static final Path JDK17_JAR =
+      Paths.get(ToolHelper.TESTS_BUILD_DIR, "examplesJava17").resolve("lambda" + JAR_EXTENSION);
+  private static final String MAIN = "lambda.Lambda";
+  private static final String EXPECTED_RESULT = "[abb, bbc]";
+
+  private final TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters()
+        .withCfRuntimesStartingFromIncluding(CfVm.JDK17)
+        .withDexRuntimes()
+        .withAllApiLevels()
+        .enableApiLevelsForCf()
+        .build();
+  }
+
+  @Test
+  public void testReference() throws Exception {
+    Assume.assumeTrue(parameters.isCfRuntime());
+    testForJvm()
+        .addProgramFiles(JDK17_JAR)
+        .run(parameters.getRuntime(), MAIN)
+        .assertSuccessWithOutputLines(EXPECTED_RESULT);
+  }
+
+  @Test
+  public void testJavaD8() throws Exception {
+    testForDesugaring(parameters)
+        .addProgramFiles(JDK17_JAR)
+        .run(parameters.getRuntime(), MAIN)
+        .assertSuccessWithOutputLines(EXPECTED_RESULT);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    Assume.assumeTrue(parameters.isDexRuntime() || parameters.getApiLevel().equals(B));
+    testForR8(parameters.getBackend())
+        .addProgramFiles(JDK17_JAR)
+        .applyIf(
+            parameters.isCfRuntime() && !parameters.getApiLevel().isEqualTo(AndroidApiLevel.B),
+            // Alternatively we need to pass Jdk17 as library.
+            b -> b.addKeepRules("-dontwarn java.lang.invoke.StringConcatFactory"))
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(MAIN)
+        .run(parameters.getRuntime(), MAIN)
+        .assertSuccessWithOutputLines(EXPECTED_RESULT);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestLambdaJava17Test.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestLambdaJava17Test.java
index 94fbe71..a166409 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestLambdaJava17Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestLambdaJava17Test.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.desugar.nestaccesscontrol;
 
-import static com.android.tools.r8.utils.AndroidApiLevel.B;
 import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
 
 import com.android.tools.r8.TestBase;
@@ -12,8 +11,7 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import org.junit.Assume;
@@ -32,7 +30,8 @@
   private static final Path JDK17_JAR =
       Paths.get(ToolHelper.TESTS_BUILD_DIR, "examplesJava17").resolve("nest" + JAR_EXTENSION);
   private static final String MAIN = "nest.NestLambda";
-  private static final String EXPECTED_RESULT = "printed: inner";
+  private static final String EXPECTED_RESULT =
+      StringUtils.lines("printed: inner", "printed from itf: here");
 
   private final TestParameters parameters;
 
@@ -40,10 +39,8 @@
   public static TestParametersCollection data() {
     return getTestParameters()
         .withCfRuntimesStartingFromIncluding(CfVm.JDK17)
-        // The test requires the java.util.function. package.
-        .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .enableApiLevelsForCf()
+        .withDexRuntimes()
+        .withAllApiLevelsAlsoForCf()
         .build();
   }
 
@@ -53,20 +50,20 @@
     testForJvm()
         .addProgramFiles(JDK17_JAR)
         .run(parameters.getRuntime(), MAIN)
-        .assertSuccessWithOutputLines(EXPECTED_RESULT);
+        .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 
   @Test
   public void testJavaD8() throws Exception {
-    testForDesugaring(parameters)
+    testForD8(parameters.getBackend())
         .addProgramFiles(JDK17_JAR)
+        .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), MAIN)
-        .assertSuccessWithOutputLines(EXPECTED_RESULT);
+        .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 
   @Test
   public void testR8() throws Exception {
-    Assume.assumeTrue(parameters.isDexRuntime() || parameters.getApiLevel().equals(B));
     testForR8(parameters.getBackend())
         .addProgramFiles(JDK17_JAR)
         .applyIf(
@@ -76,6 +73,6 @@
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(MAIN)
         .run(parameters.getRuntime(), MAIN)
-        .assertSuccessWithOutputLines(EXPECTED_RESULT);
+        .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
index 9d13687..d5f5e91 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
@@ -55,7 +55,6 @@
             DexEncodedMethod.builder()
                 .setMethod(signature)
                 .setAccessFlags(MethodAccessFlags.fromDexAccessFlags(0))
-                .setCode(null)
                 .disableAndroidApiLevelCheck()
                 .build());
     return new Node(method);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendAppendNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendAppendNotNullTest.java
new file mode 100644
index 0000000..5cde367
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendAppendNotNullTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendAppendNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(2, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : null;
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : "o";
+      System.out.println(new StringBuilder().append(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendAppendTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendAppendTest.java
new file mode 100644
index 0000000..3840d75
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendAppendTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendAppendTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(2, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : null;
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : null;
+      System.out.println(new StringBuilder().append(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendConstantAppendNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendConstantAppendNotNullTest.java
new file mode 100644
index 0000000..d4ac494
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendConstantAppendNotNullTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendNotNullAppendConstantAppendNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "oko";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              // TODO(b/129200243): Should only have two appends.
+              assertEquals(3, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : "";
+      System.out.println(new StringBuilder().append(arg).append("k").append(arg).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendNotNullTest.java
new file mode 100644
index 0000000..c28729a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendNotNullTest.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendNotNullAppendNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): Should be String.concat.
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(2, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : "";
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : "";
+      System.out.println(new StringBuilder().append(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendTest.java
new file mode 100644
index 0000000..21b61f3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullAppendTest.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendNotNullAppendTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): See if this can be arg1.concat(String.valueOf(arg2))
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(2, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : "";
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : null;
+      System.out.println(new StringBuilder().append(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullTest.java
new file mode 100644
index 0000000..d2c95ab
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendNotNullTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "o";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): This should just be arg.toString()
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : "";
+      System.out.println(new StringBuilder().append(arg).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendTest.java
new file mode 100644
index 0000000..534591f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatAppendTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatAppendTest extends TestBase {
+
+  private static final String EXPECTED = "o";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : null;
+      System.out.println(new StringBuilder().append(arg).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatConstantInitTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatConstantInitTest.java
new file mode 100644
index 0000000..9b9280f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatConstantInitTest.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatConstantInitTest extends TestBase {
+
+  private static final String EXPECTED = "oko";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): Should be String.concat.
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : null;
+      if (arg != null) {
+        // The optimization should join "ok" into init and then append with arg.
+        System.out.println(new StringBuilder("o").append("k").append(arg).toString());
+      }
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatImplicitToStringConcatTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatImplicitToStringConcatTest.java
new file mode 100644
index 0000000..a2eb814
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatImplicitToStringConcatTest.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatImplicitToStringConcatTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): This should be String.concat() as argument.
+              assertEquals(2, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : null;
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : null;
+      if (arg1 != null && arg2 != null) {
+        System.out.println(new StringBuilder(new StringBuilder(arg1).append(arg2)).toString());
+      }
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatImplicitToStringSingleTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatImplicitToStringSingleTest.java
new file mode 100644
index 0000000..a3eb034
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatImplicitToStringSingleTest.java
@@ -0,0 +1,70 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatImplicitToStringSingleTest extends TestBase {
+
+  private static final String EXPECTED = "o";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): Use the arg string directly as input.
+              assertEquals(2, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(0, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : null;
+      if (arg != null) {
+        System.out.println(new StringBuilder(new StringBuilder(arg)).toString());
+      }
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitAppendNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitAppendNotNullTest.java
new file mode 100644
index 0000000..3f6f896
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitAppendNotNullTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatInitAppendNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : null;
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : "";
+      System.out.println(new StringBuilder(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitAppendTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitAppendTest.java
new file mode 100644
index 0000000..d7ace15
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitAppendTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatInitAppendTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : null;
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : null;
+      System.out.println(new StringBuilder(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullAppendNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullAppendNotNullTest.java
new file mode 100644
index 0000000..4dce8fd
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullAppendNotNullTest.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatInitNotNullAppendNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): Should be concat.
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : "";
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : "";
+      System.out.println(new StringBuilder(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullAppendTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullAppendTest.java
new file mode 100644
index 0000000..3579f20
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullAppendTest.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatInitNotNullAppendTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): See if this can be arg1.concat(String.valueOf(arg2))
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(1, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg1 = System.currentTimeMillis() > 0 ? "o" : "";
+      String arg2 = System.currentTimeMillis() > 0 ? "k" : null;
+      System.out.println(new StringBuilder(arg1).append(arg2).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullTest.java
new file mode 100644
index 0000000..690a604
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitNotNullTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatInitNotNullTest extends TestBase {
+
+  private static final String EXPECTED = "o";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              // TODO(b/129200243): This should just be the string as is.
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(0, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : "";
+      System.out.println(new StringBuilder(arg).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitTest.java
new file mode 100644
index 0000000..44aa31b3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatInitTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatInitTest extends TestBase {
+
+  private static final String EXPECTED = "o";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(1, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(0, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      String arg = System.currentTimeMillis() > 0 ? "o" : null;
+      System.out.println(new StringBuilder(arg).toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatNoRewriteConstantsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatNoRewriteConstantsTest.java
new file mode 100644
index 0000000..73e61bc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatNoRewriteConstantsTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.string;
+
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderAppends;
+import static com.android.tools.r8.ir.optimize.string.utils.StringBuilderCodeMatchers.countStringBuilderInits;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StringConcatNoRewriteConstantsTest extends TestBase {
+
+  private static final String EXPECTED = "ok";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED)
+        .inspect(
+            inspect -> {
+              MethodSubject methodSubject = inspect.clazz(Main.class).mainMethod();
+              assertThat(methodSubject, isPresent());
+              assertEquals(0, countStringBuilderInits(methodSubject.asFoundMethodSubject()));
+              assertEquals(0, countStringBuilderAppends(methodSubject.asFoundMethodSubject()));
+            });
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      // Should just be a single constant string without string.concat.
+      System.out.println(new StringBuilder("o").append("k").toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/utils/StringBuilderCodeMatchers.java b/src/test/java/com/android/tools/r8/ir/optimize/string/utils/StringBuilderCodeMatchers.java
index 08abff5..e60fb1c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/utils/StringBuilderCodeMatchers.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/utils/StringBuilderCodeMatchers.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.ir.optimize.string.utils;
 
 import com.android.tools.r8.utils.codeinspector.CodeMatchers;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import java.util.function.Predicate;
 
@@ -14,4 +15,23 @@
     return CodeMatchers.isInvokeWithTarget(
         "java.lang.StringBuilder", "java.lang.StringBuilder", "append", "java.lang.String");
   }
+
+  public static long countStringBuilderInits(FoundMethodSubject method) {
+    return countInstructionsOnStringBuilder(method, "<init>");
+  }
+
+  public static long countStringBuilderAppends(FoundMethodSubject method) {
+    return countInstructionsOnStringBuilder(method, "append");
+  }
+
+  public static long countInstructionsOnStringBuilder(
+      FoundMethodSubject method, String methodName) {
+    return method
+        .streamInstructions()
+        .filter(
+            instructionSubject ->
+                CodeMatchers.isInvokeWithTarget(StringBuilder.class.getTypeName(), methodName)
+                    .test(instructionSubject))
+        .count();
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
index 3486422..5a7846e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
@@ -4,9 +4,8 @@
 
 package com.android.tools.r8.kotlin;
 
-import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_3_72;
-import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_4_20;
-import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLIN_DEV;
+import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_5_0;
+import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_6_0;
 
 import com.android.tools.r8.KotlinTestParameters;
 import com.android.tools.r8.TestParameters;
@@ -63,7 +62,7 @@
   }
 
   @Test
-  public void test_dataclass_gettersOnly() throws Exception {
+  public void testDataclassGettersOnly() throws Exception {
     String mainClassName = "dataclass.MainGettersOnlyKt";
     MethodSignature testMethodSignature =
         new MethodSignature("testDataClassGetters", "void", Collections.emptyList());
@@ -99,7 +98,7 @@
   }
 
   @Test
-  public void test_dataclass_componentOnly() throws Exception {
+  public void testDataclassComponentOnly() throws Exception {
     String mainClassName = "dataclass.MainComponentOnlyKt";
     MethodSignature testMethodSignature =
         new MethodSignature("testAllDataClassComponentFunctions", "void", Collections.emptyList());
@@ -135,7 +134,7 @@
   }
 
   @Test
-  public void test_dataclass_componentPartial() throws Exception {
+  public void testDataclassComponentPartial() throws Exception {
     String mainClassName = "dataclass.MainComponentPartialKt";
     MethodSignature testMethodSignature =
         new MethodSignature("testSomeDataClassComponentFunctions", "void", Collections.emptyList());
@@ -178,7 +177,7 @@
   }
 
   @Test
-  public void test_dataclass_copyIsRemovedIfNotUsed() throws Exception {
+  public void testDataclassCopyIsRemovedIfNotUsed() throws Exception {
     String mainClassName = "dataclass.MainComponentOnlyKt";
     MethodSignature testMethodSignature =
         new MethodSignature("testDataClassCopy", "void", Collections.emptyList());
@@ -203,7 +202,7 @@
   }
 
   @Test
-  public void test_dataclass_copyDefaultIsRemovedIfNotUsed() throws Exception {
+  public void testDataclassCopyDefaultIsRemovedIfNotUsed() throws Exception {
     String mainClassName = "dataclass.MainCopyKt";
     MethodSignature testMethodSignature =
         new MethodSignature("testDataClassCopyWithDefault", "void", Collections.emptyList());
@@ -216,10 +215,10 @@
                     .addOptionsModification(disableClassInliner))
         .inspect(
             inspector -> {
-              // TODO(b/210828502): Investigate why Person is not removed with kotlin dev.
+              // TODO(b/210828502): Investigate why Person is not removed with kotlin 1.7 and 1.8.
               if (allowAccessModification
-                  && !(kotlinc.isOneOf(KOTLINC_1_3_72, KOTLINC_1_4_20, KOTLIN_DEV)
-                      && testParameters.isCfRuntime())) {
+                  && (kotlinc.isOneOf(KOTLINC_1_5_0, KOTLINC_1_6_0)
+                      || testParameters.isDexRuntime())) {
                 checkClassIsRemoved(inspector, TEST_DATA_CLASS.getClassName());
               } else {
                 ClassSubject dataClass =
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingDebugTest.java b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingDebugTest.java
index d426170..69f454d 100644
--- a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingDebugTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingDebugTest.java
@@ -6,7 +6,6 @@
 import static org.hamcrest.CoreMatchers.equalTo;
 
 import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.KotlinCompilerTool.KotlinTargetVersion;
 import com.android.tools.r8.KotlinTestBase;
 import com.android.tools.r8.KotlinTestParameters;
 import com.android.tools.r8.TestParameters;
@@ -45,7 +44,7 @@
     testForR8(parameters.getBackend())
         .setMode(CompilationMode.DEBUG)
         .addProgramFiles(
-            compiledJars.getForConfiguration(kotlinc, KotlinTargetVersion.JAVA_6),
+            compiledJars.getForConfiguration(kotlinc, kotlinParameters.getTargetVersion()),
             kotlinc.getKotlinAnnotationJar())
         .addProgramFiles(getJavaJarFile(FOLDER))
         .setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java
index aa3a51d..452ca8a 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java
@@ -51,7 +51,7 @@
   }
 
   private String replaceInitNameInExpectedBasedOnKotlinVersion(String expected) {
-    return kotlinParameters.isNewerThanOrEqualTo(KotlinCompilerVersion.KOTLIN_DEV)
+    return kotlinParameters.isNewerThanOrEqualTo(KotlinCompilerVersion.KOTLINC_1_7_0)
         ? expected.replace("<init>", "`<init>`")
         : expected;
   }
diff --git a/src/test/java/com/android/tools/r8/kotlin/stringplus/StringPlusTest.java b/src/test/java/com/android/tools/r8/kotlin/stringplus/StringPlusTest.java
index 37b20bd..d189806 100644
--- a/src/test/java/com/android/tools/r8/kotlin/stringplus/StringPlusTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/stringplus/StringPlusTest.java
@@ -97,7 +97,7 @@
               MethodSubject methodSubject = clazz.mainMethod();
               assertThat(methodSubject, isPresent());
               if (kotlinParameters.isNewerThanOrEqualTo(KotlinCompilerVersion.KOTLINC_1_5_0)
-                  && kotlinParameters.isOlderThan(KotlinCompilerVersion.KOTLIN_DEV)) {
+                  && kotlinParameters.isOlderThan(KotlinCompilerVersion.KOTLINC_1_7_0)) {
                 // TODO(b/190489514): We should be able to optimize constant stringPlus calls.
                 assertThat(methodSubject, CodeMatchers.invokesMethodWithName("stringPlus"));
               }
diff --git a/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java b/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java
index 1ea73cc..80d580b 100644
--- a/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.TestDiagnosticMessagesImpl;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.retrace.stacktraces.InlineFileNameStackTrace;
+import com.android.tools.r8.retrace.stacktraces.LongLineStackTrace;
 import com.android.tools.r8.retrace.stacktraces.RetraceAssertionErrorStackTrace;
 import com.android.tools.r8.retrace.stacktraces.StackTraceForTest;
 import com.android.tools.r8.utils.BooleanUtils;
@@ -1088,7 +1089,7 @@
   @Test
   public void testGroups() {
     runRetraceTest(
-        "(?:(?:.*?%c %m\\(%s(?:: %l)?\\)))",
+        "(?:(?:.*?%c %m\\(%s\\s*:\\s*%l\\s*\\)))",
         new StackTraceForTest() {
           @Override
           public List<String> obfuscatedStackTrace() {
@@ -1113,9 +1114,9 @@
             return ImmutableList.of(
                 "this.was.Deobfuscated someMethod(Deobfuscated.java: 65)",
                 "this.was.Deobfuscated someMethod(Deobfuscated.java: 65)",
-                "FOO bar(PG:1)",
-                "FOO bar(PG:1 )",
-                "FOO bar(PG: 1 )");
+                "this.was.Deobfuscated someMethod(Deobfuscated.java:65)",
+                "this.was.Deobfuscated someMethod(Deobfuscated.java:65 )",
+                "this.was.Deobfuscated someMethod(Deobfuscated.java: 65 )");
           }
 
           @Override
@@ -1123,9 +1124,9 @@
             return ImmutableList.of(
                 "this.was.Deobfuscated void someMethod(int)(Deobfuscated.java: 65)",
                 "this.was.Deobfuscated void someMethod(int)(Deobfuscated.java: 65)",
-                "FOO bar(PG:1)",
-                "FOO bar(PG:1 )",
-                "FOO bar(PG: 1 )");
+                "this.was.Deobfuscated void someMethod(int)(Deobfuscated.java:65)",
+                "this.was.Deobfuscated void someMethod(int)(Deobfuscated.java:65 )",
+                "this.was.Deobfuscated void someMethod(int)(Deobfuscated.java: 65 )");
           }
 
           @Override
@@ -1135,6 +1136,12 @@
         });
   }
 
+  /** This is a regression test for b/234758957 */
+  @Test()
+  public void testLongLine() {
+    runRetraceTest("(?:.*?\\(\\s*%s(?:\\s*:\\s*%l\\s*)?\\)\\s*%c\\.%m)|", new LongLineStackTrace());
+  }
+
   private TestDiagnosticMessagesImpl runRetraceTest(
       String regularExpression, StackTraceForTest stackTraceForTest) {
     TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/LongLineStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/LongLineStackTrace.java
new file mode 100644
index 0000000..0ab5396
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/LongLineStackTrace.java
@@ -0,0 +1,96 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class LongLineStackTrace implements StackTraceForTest {
+
+  @Override
+  public List<String> obfuscatedStackTrace() {
+    return Arrays.asList(
+        "asdf():::asfasidfsadfsafassdfsalfkaskldfasjkl908435 439593409 5309 843 5980349085 9043598"
+            + " 04930 5 9084389 549 385 908435098435980 4390 5890435908 4389 0509345890"
+            + " 23904239s909090safasiofas90f0-safads0-fas0-f-0f-0fasdf0-asswioj df jaiowj fioweoji"
+            + " fqiwope fopiwqej fqweiopj fwqejiof qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu"
+            + " t8324981qu2398 rt3289 rt2489t euhiorjg kdfgf8u432iojt3u8io432jk t3u49t 489u4389u"
+            + " t438u9 t43y89t 3 489t y8934t34 89ytu8943tu8 984u3 t"
+            + " 8u934asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgf8u432iojt3u8io432jk t3u49t 489u4389u t438u9 t43y89t 3 489t y8934t34"
+            + " 89ytu8943tu8 984u3 t"
+            + " 8u93asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgf8u432iojt3u8io432jk t3u49t 489u4389u t438u9 t43y89t 3 489t y8934t34"
+            + " 89ytu8943tu8 984u3 t"
+            + " 8u9344asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgfasdfsdf123asdfas9dfas09df9a090asdasdfasfasdf290909009fw90wf9w0f9e09w0f90w");
+  }
+
+  @Override
+  public String mapping() {
+    return "";
+  }
+
+  @Override
+  public List<String> retracedStackTrace() {
+    return Arrays.asList(
+        "asdf():::asfasidfsadfsafassdfsalfkaskldfasjkl908435 439593409 5309 843 5980349085 9043598"
+            + " 04930 5 9084389 549 385 908435098435980 4390 5890435908 4389 0509345890"
+            + " 23904239s909090safasiofas90f0-safads0-fas0-f-0f-0fasdf0-asswioj df jaiowj fioweoji"
+            + " fqiwope fopiwqej fqweiopj fwqejiof qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu"
+            + " t8324981qu2398 rt3289 rt2489t euhiorjg kdfgf8u432iojt3u8io432jk t3u49t 489u4389u"
+            + " t438u9 t43y89t 3 489t y8934t34 89ytu8943tu8 984u3 t"
+            + " 8u934asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgf8u432iojt3u8io432jk t3u49t 489u4389u t438u9 t43y89t 3 489t y8934t34"
+            + " 89ytu8943tu8 984u3 t"
+            + " 8u93asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgf8u432iojt3u8io432jk t3u49t 489u4389u t438u9 t43y89t 3 489t y8934t34"
+            + " 89ytu8943tu8 984u3 t"
+            + " 8u9344asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgfasdfsdf123asdfas9dfas09df9a090asdasdfasfasdf290909009fw90wf9w0f9e09w0f90w");
+  }
+
+  @Override
+  public List<String> retraceVerboseStackTrace() {
+    return Arrays.asList(
+        "asdf():::asfasidfsadfsafassdfsalfkaskldfasjkl908435 439593409 5309 843 5980349085 9043598"
+            + " 04930 5 9084389 549 385 908435098435980 4390 5890435908 4389 0509345890"
+            + " 23904239s909090safasiofas90f0-safads0-fas0-f-0f-0fasdf0-asswioj df jaiowj fioweoji"
+            + " fqiwope fopiwqej fqweiopj fwqejiof qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu"
+            + " t8324981qu2398 rt3289 rt2489t euhiorjg kdfgf8u432iojt3u8io432jk t3u49t 489u4389u"
+            + " t438u9 t43y89t 3 489t y8934t34 89ytu8943tu8 984u3 t"
+            + " 8u934asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgf8u432iojt3u8io432jk t3u49t 489u4389u t438u9 t43y89t 3 489t y8934t34"
+            + " 89ytu8943tu8 984u3 t"
+            + " 8u93asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgf8u432iojt3u8io432jk t3u49t 489u4389u t438u9 t43y89t 3 489t y8934t34"
+            + " 89ytu8943tu8 984u3 t"
+            + " 8u9344asdf(:asdfas0dfasd0fa0)S)DFD)SDF_SD)FSDKFJlsalk;dfjaklsdf())(SDFSdfaklsdfas0d9fwe89rio223oi4rwoiuqaoiwqiowpjaklcvewtujoiwrjweof"
+            + " asdfjaswdj foisadj f aswioj df jaiowj fioweoji fqiwope fopiwqej fqweiopj fwqejiof"
+            + " qwoepijf eiwoj fqwioepjf wiqeof jqweoifiqu t8324981qu2398 rt3289 rt2489t euhiorjg"
+            + " kdfgfasdfsdf123asdfas9dfas09df9a090asdasdfasfasdf290909009fw90wf9w0f9e09w0f90w");
+  }
+
+  @Override
+  public int expectedWarnings() {
+    return 0;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/startup/GenerateInstrumentationServerClassesTest.java b/src/test/java/com/android/tools/r8/startup/GenerateInstrumentationServerClassesTest.java
new file mode 100644
index 0000000..5e7c7c5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/startup/GenerateInstrumentationServerClassesTest.java
@@ -0,0 +1,82 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.startup;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.cfmethodgeneration.CfClassGenerator;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.FileUtils;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class GenerateInstrumentationServerClassesTest extends TestBase {
+
+  @Parameter(0)
+  public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withCfRuntime(CfVm.JDK9).build();
+  }
+
+  @Test
+  public void testInstrumentationServerClassesGenerated() throws IOException {
+    for (CfClassGenerator classGenerator : getClassGenerators()) {
+      assertEquals(
+          FileUtils.readTextFile(classGenerator.getGeneratedFile(), StandardCharsets.UTF_8),
+          classGenerator.generateClass());
+    }
+  }
+
+  public static void main(String[] args) throws IOException {
+    for (CfClassGenerator classGenerator : getClassGenerators()) {
+      classGenerator.writeClassToFile();
+    }
+  }
+
+  private static List<CfClassGenerator> getClassGenerators() {
+    return ImmutableList.of(
+        new InstrumentationServerClassGenerator(InstrumentationServer.class),
+        new InstrumentationServerClassGenerator(InstrumentationServerImpl.class));
+  }
+
+  private static class InstrumentationServerClassGenerator extends CfClassGenerator {
+
+    private final Class<?> clazz;
+
+    InstrumentationServerClassGenerator(Class<?> clazz) {
+      this.clazz = clazz;
+    }
+
+    @Override
+    protected DexType getGeneratedType() {
+      return factory.createType(
+          "Lcom/android/tools/r8/startup/generated/" + clazz.getSimpleName() + "Factory;");
+    }
+
+    @Override
+    public Class<?> getImplementation() {
+      return clazz;
+    }
+
+    @Override
+    protected int getYear() {
+      return 2022;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/startup/InstrumentationServer.java b/src/test/java/com/android/tools/r8/startup/InstrumentationServer.java
new file mode 100644
index 0000000..b920b35
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/startup/InstrumentationServer.java
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.startup;
+
+import java.io.File;
+import java.io.IOException;
+
+public abstract class InstrumentationServer {
+
+  public static InstrumentationServer getInstance() {
+    return InstrumentationServerImpl.getInstance();
+  }
+
+  public abstract void writeToFile(File file) throws IOException;
+}
diff --git a/src/test/java/com/android/tools/r8/startup/InstrumentationServerImpl.java b/src/test/java/com/android/tools/r8/startup/InstrumentationServerImpl.java
new file mode 100644
index 0000000..9893c44
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/startup/InstrumentationServerImpl.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.startup;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+public class InstrumentationServerImpl extends InstrumentationServer {
+
+  private static final InstrumentationServerImpl INSTANCE = new InstrumentationServerImpl();
+
+  private final StringBuilder builder = new StringBuilder();
+
+  // May be set to true by the instrumentation.
+  private final boolean writeToLogcat = false;
+  private final String logcatTag = "r8";
+
+  private InstrumentationServerImpl() {}
+
+  public static InstrumentationServerImpl getInstance() {
+    return InstrumentationServerImpl.INSTANCE;
+  }
+
+  public static void addNonSyntheticMethod(String descriptor) {
+    getInstance().addLine(descriptor);
+  }
+
+  public static void addSyntheticMethod(String descriptor) {
+    getInstance().addLine('S' + descriptor);
+  }
+
+  private synchronized void addLine(String line) {
+    if (writeToLogcat) {
+      writeToLogcat(line);
+    } else {
+      builder.append(line).append('\n');
+    }
+  }
+
+  @Override
+  public synchronized void writeToFile(File file) throws IOException {
+    FileOutputStream stream = new FileOutputStream(file);
+    try {
+      stream.write(builder.toString().getBytes(Charset.forName("UTF-8")));
+    } finally {
+      stream.close();
+    }
+  }
+
+  private void writeToLogcat(String line) {
+    android.util.Log.v(logcatTag, line);
+  }
+}
diff --git a/third_party/kotlin/kotlin-compiler-1.7.0.tar.gz.sha1 b/third_party/kotlin/kotlin-compiler-1.7.0.tar.gz.sha1
new file mode 100644
index 0000000..3fb628e
--- /dev/null
+++ b/third_party/kotlin/kotlin-compiler-1.7.0.tar.gz.sha1
@@ -0,0 +1 @@
+55d90d044b7f6809c80183b46f73bdbb9ebf7eaf
\ No newline at end of file
diff --git a/tools/compiledump.py b/tools/compiledump.py
index c6a4a19..6baaada 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -139,6 +139,11 @@
     help='Run as a platform build',
     default=False,
     action='store_true')
+  parser.add_argument(
+    '--compilation-mode', '--compilation_mode',
+    help='Run compilation in specified mode',
+    choices=['debug', 'release'],
+    default=None)
   return parser
 
 def error(msg):
@@ -283,17 +288,18 @@
 
 def determine_android_platform_build(args, build_properties):
   if args.android_platform_build:
-    return args.android_platform_build
-  if 'android-platform-build=true' in build_properties:
     return True
-  return None
+  return build_properties.get('android-platform-build') == 'true'
 
 def determine_enable_missing_library_api_modeling(args, build_properties):
   if args.enable_missing_library_api_modeling:
-    return args.enable_missing_library_api_modeling
-  if 'enable-missing-library-api-modeling=true' in build_properties:
     return True
-  return None
+  return build_properties.get('enable-missing-library-api-modeling') == 'true'
+
+def determine_compilation_mode(args, build_properties):
+  if args.compilation_mode:
+    return args.compilation_mode
+  return build_properties.get('mode')
 
 def determine_properties(build_properties):
   args = []
@@ -407,6 +413,7 @@
     classfile = determine_class_file(args, build_properties)
     android_platform_build = determine_android_platform_build(args, build_properties)
     enable_missing_library_api_modeling = determine_enable_missing_library_api_modeling(args, build_properties)
+    mode = determine_compilation_mode(args, build_properties)
     jar = args.r8_jar if args.r8_jar else download_distribution(version, args.nolib, temp)
     if ':' not in jar and not os.path.exists(jar):
       error("Distribution does not exist: " + jar)
@@ -439,6 +446,10 @@
       cmd.append('com.android.tools.r8.utils.CompileDumpCompatR8')
     if compiler == 'r8':
       cmd.append('--compat')
+    if mode == 'debug':
+      cmd.append('--debug')
+    else:
+      cmd.append('--release')
     # For recompilation of dumps run_on_app_dumps pass in a program jar.
     cmd.append(determine_program_jar(args, dump))
     cmd.extend(['--output', out])