Option to enable startup/non-startup boundary optimizations

Change-Id: I0a0037e9fef75e9810990600688ac44bee508b08
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 31967b1..a64b883 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -166,7 +166,7 @@
     }
     Path dumpOutput = dumpInputFlags.getDumpPath();
     timing.begin("ApplicationReader.dump");
-    inputApp.dump(dumpOutput, dumpOptions, options.reporter, options.dexItemFactory());
+    inputApp.dump(dumpOutput, dumpOptions, options);
     timing.end();
     Diagnostic message = new StringDiagnostic("Dumped compilation inputs to: " + dumpOutput);
     if (dumpInputFlags.shouldFailCompilation()) {
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java
index 47c7834..0a97199 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java
@@ -18,6 +18,16 @@
           "com.android.tools.r8.startup.minimalstartupdex", false);
 
   /**
+   * When enabled, optimizations crossing the startup/non-startup boundary will be allowed.
+   *
+   * <p>The disabling of this may help to avoid that more code may be loaded during startup as a
+   * result of optimizations such as inlining and class merging.
+   */
+  private boolean enableStartupBoundaryOptimizations =
+      parseSystemPropertyForDevelopmentOrDefault(
+          "com.android.tools.r8.startup.boundaryoptimizations", false);
+
+  /**
    * When enabled, each method that is not classified as a startup method at the end of compilation
    * will be changed to have a throwing method body.
    *
@@ -101,6 +111,10 @@
     return this;
   }
 
+  public boolean isStartupBoundaryOptimizationsEnabled() {
+    return enableStartupBoundaryOptimizations;
+  }
+
   public boolean isStartupInstrumentationEnabled() {
     return enableStartupInstrumentation;
   }
diff --git a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
index 2113b52..5b8e3db 100644
--- a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
+++ b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
@@ -107,14 +107,20 @@
   public Map<FeatureSplit, Set<DexProgramClass>> getFeatureSplitClasses(
       Set<DexProgramClass> classes, AppView<? extends AppInfoWithClassHierarchy> appView) {
     return getFeatureSplitClasses(
-        classes, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        classes,
+        appView.options(),
+        appView.appInfo().getStartupOrder(),
+        appView.getSyntheticItems());
   }
 
   public Map<FeatureSplit, Set<DexProgramClass>> getFeatureSplitClasses(
-      Set<DexProgramClass> classes, StartupOrder startupOrder, SyntheticItems syntheticItems) {
+      Set<DexProgramClass> classes,
+      InternalOptions options,
+      StartupOrder startupOrder,
+      SyntheticItems syntheticItems) {
     Map<FeatureSplit, Set<DexProgramClass>> result = new IdentityHashMap<>();
     for (DexProgramClass clazz : classes) {
-      FeatureSplit featureSplit = getFeatureSplit(clazz, startupOrder, syntheticItems);
+      FeatureSplit featureSplit = getFeatureSplit(clazz, options, startupOrder, syntheticItems);
       if (featureSplit != null && !featureSplit.isBase()) {
         result.computeIfAbsent(featureSplit, ignore -> Sets.newIdentityHashSet()).add(clazz);
       }
@@ -125,21 +131,31 @@
   public FeatureSplit getFeatureSplit(
       ProgramDefinition definition, AppView<? extends AppInfoWithClassHierarchy> appView) {
     return getFeatureSplit(
-        definition, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        definition,
+        appView.options(),
+        appView.appInfo().getStartupOrder(),
+        appView.getSyntheticItems());
   }
 
   public FeatureSplit getFeatureSplit(
-      ProgramDefinition definition, StartupOrder startupOrder, SyntheticItems syntheticItems) {
-    return getFeatureSplit(definition.getContextType(), startupOrder, syntheticItems);
+      ProgramDefinition definition,
+      InternalOptions options,
+      StartupOrder startupOrder,
+      SyntheticItems syntheticItems) {
+    return getFeatureSplit(definition.getContextType(), options, startupOrder, syntheticItems);
   }
 
   public FeatureSplit getFeatureSplit(
       DexType type, AppView<? extends AppInfoWithClassHierarchy> appView) {
-    return getFeatureSplit(type, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+    return getFeatureSplit(
+        type, appView.options(), appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
   }
 
   public FeatureSplit getFeatureSplit(
-      DexType type, StartupOrder startupOrder, SyntheticItems syntheticItems) {
+      DexType type,
+      InternalOptions options,
+      StartupOrder startupOrder,
+      SyntheticItems syntheticItems) {
     if (syntheticItems == null) {
       // Called from AndroidApp.dumpProgramResources().
       assert startupOrder.isEmpty();
@@ -154,16 +170,20 @@
         // the shared utility class in case it is used during startup. The use of base startup
         // allows for merging startup classes with the shared utility class, however, which could be
         // bad for startup if the shared utility class is not used during startup.
-        return startupOrder.isEmpty() ? FeatureSplit.BASE : FeatureSplit.BASE_STARTUP;
+        return startupOrder.isEmpty()
+                || options.getStartupOptions().isStartupBoundaryOptimizationsEnabled()
+            ? FeatureSplit.BASE
+            : FeatureSplit.BASE_STARTUP;
       }
       feature = syntheticItems.getContextualFeatureSplitOrDefault(type, FeatureSplit.BASE);
     } else {
       feature = classToFeatureSplitMap.getOrDefault(type, FeatureSplit.BASE);
     }
     if (feature.isBase()) {
-      return startupOrder.contains(type, syntheticItems)
-          ? FeatureSplit.BASE_STARTUP
-          : FeatureSplit.BASE;
+      return !startupOrder.contains(type, syntheticItems)
+              || options.getStartupOptions().isStartupBoundaryOptimizationsEnabled()
+          ? FeatureSplit.BASE
+          : FeatureSplit.BASE_STARTUP;
     }
     return feature;
   }
@@ -177,12 +197,16 @@
 
   public boolean isInBase(
       DexProgramClass clazz, AppView<? extends AppInfoWithClassHierarchy> appView) {
-    return isInBase(clazz, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+    return isInBase(
+        clazz, appView.options(), appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
   }
 
   public boolean isInBase(
-      DexProgramClass clazz, StartupOrder startupOrder, SyntheticItems syntheticItems) {
-    return getFeatureSplit(clazz, startupOrder, syntheticItems).isBase();
+      DexProgramClass clazz,
+      InternalOptions options,
+      StartupOrder startupOrder,
+      SyntheticItems syntheticItems) {
+    return getFeatureSplit(clazz, options, startupOrder, syntheticItems).isBase();
   }
 
   public boolean isInBaseOrSameFeatureAs(
@@ -190,15 +214,21 @@
       ProgramDefinition context,
       AppView<? extends AppInfoWithClassHierarchy> appView) {
     return isInBaseOrSameFeatureAs(
-        clazz, context, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        clazz,
+        context,
+        appView.options(),
+        appView.appInfo().getStartupOrder(),
+        appView.getSyntheticItems());
   }
 
   public boolean isInBaseOrSameFeatureAs(
       DexProgramClass clazz,
       ProgramDefinition context,
+      InternalOptions options,
       StartupOrder startupOrder,
       SyntheticItems syntheticItems) {
-    return isInBaseOrSameFeatureAs(clazz.getContextType(), context, startupOrder, syntheticItems);
+    return isInBaseOrSameFeatureAs(
+        clazz.getContextType(), context, options, startupOrder, syntheticItems);
   }
 
   public boolean isInBaseOrSameFeatureAs(
@@ -206,48 +236,62 @@
       ProgramDefinition context,
       AppView<? extends AppInfoWithClassHierarchy> appView) {
     return isInBaseOrSameFeatureAs(
-        clazz, context, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        clazz,
+        context,
+        appView.options(),
+        appView.appInfo().getStartupOrder(),
+        appView.getSyntheticItems());
   }
 
   public boolean isInBaseOrSameFeatureAs(
       DexType clazz,
       ProgramDefinition context,
+      InternalOptions options,
       StartupOrder startupOrder,
       SyntheticItems syntheticItems) {
-    FeatureSplit split = getFeatureSplit(clazz, startupOrder, syntheticItems);
-    return split.isBase() || split == getFeatureSplit(context, startupOrder, syntheticItems);
+    FeatureSplit split = getFeatureSplit(clazz, options, startupOrder, syntheticItems);
+    return split.isBase()
+        || split == getFeatureSplit(context, options, startupOrder, syntheticItems);
   }
 
   public boolean isInFeature(
-      DexProgramClass clazz, StartupOrder startupOrder, SyntheticItems syntheticItems) {
-    return !isInBase(clazz, startupOrder, syntheticItems);
+      DexProgramClass clazz,
+      InternalOptions options,
+      StartupOrder startupOrder,
+      SyntheticItems syntheticItems) {
+    return !isInBase(clazz, options, startupOrder, syntheticItems);
   }
 
   public boolean isInSameFeatureOrBothInSameBase(
       ProgramMethod a, ProgramMethod b, AppView<? extends AppInfoWithClassHierarchy> appView) {
     return isInSameFeatureOrBothInSameBase(
-        a, b, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        a, b, appView.options(), appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
   }
 
   public boolean isInSameFeatureOrBothInSameBase(
-      ProgramMethod a, ProgramMethod b, StartupOrder startupOrder, SyntheticItems syntheticItems) {
+      ProgramMethod a,
+      ProgramMethod b,
+      InternalOptions options,
+      StartupOrder startupOrder,
+      SyntheticItems syntheticItems) {
     return isInSameFeatureOrBothInSameBase(
-        a.getHolder(), b.getHolder(), startupOrder, syntheticItems);
+        a.getHolder(), b.getHolder(), options, startupOrder, syntheticItems);
   }
 
   public boolean isInSameFeatureOrBothInSameBase(
       DexProgramClass a, DexProgramClass b, AppView<? extends AppInfoWithClassHierarchy> appView) {
     return isInSameFeatureOrBothInSameBase(
-        a, b, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        a, b, appView.options(), appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
   }
 
   public boolean isInSameFeatureOrBothInSameBase(
       DexProgramClass a,
       DexProgramClass b,
+      InternalOptions options,
       StartupOrder startupOrder,
       SyntheticItems syntheticItems) {
-    return getFeatureSplit(a, startupOrder, syntheticItems)
-        == getFeatureSplit(b, startupOrder, syntheticItems);
+    return getFeatureSplit(a, options, startupOrder, syntheticItems)
+        == getFeatureSplit(b, options, startupOrder, syntheticItems);
   }
 
   public ClassToFeatureSplitMap rewrittenWithLens(GraphLens lens) {
@@ -287,6 +331,10 @@
 
   public static boolean isInFeature(DexProgramClass clazz, AppView<AppInfoWithLiveness> appView) {
     return getMap(appView)
-        .isInFeature(clazz, appView.appInfo().getStartupOrder(), appView.getSyntheticItems());
+        .isInFeature(
+            clazz,
+            appView.options(),
+            appView.appInfo().getStartupOrder(),
+            appView.getSyntheticItems());
   }
 }
diff --git a/src/main/java/com/android/tools/r8/graph/AccessControl.java b/src/main/java/com/android/tools/r8/graph/AccessControl.java
index 428d0fd..43bbfa2 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessControl.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessControl.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.experimental.startup.StartupOrder;
 import com.android.tools.r8.features.ClassToFeatureSplitMap;
 import com.android.tools.r8.synthesis.SyntheticItems;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.OptionalBool;
 
 /**
@@ -24,6 +25,7 @@
         clazz,
         context,
         appView.appInfo().getClassToFeatureSplitMap(),
+        appView.options(),
         appView.appInfo().getStartupOrder(),
         appView.getSyntheticItems());
   }
@@ -32,6 +34,7 @@
       DexClass clazz,
       Definition context,
       ClassToFeatureSplitMap classToFeatureSplitMap,
+      InternalOptions options,
       StartupOrder startupOrder,
       SyntheticItems syntheticItems) {
     if (!clazz.isPublic() && !clazz.getType().isSamePackage(context.getContextType())) {
@@ -40,7 +43,11 @@
     if (clazz.isProgramClass()
         && context.isProgramDefinition()
         && !classToFeatureSplitMap.isInBaseOrSameFeatureAs(
-            clazz.asProgramClass(), context.asProgramDefinition(), startupOrder, syntheticItems)) {
+            clazz.asProgramClass(),
+            context.asProgramDefinition(),
+            options,
+            startupOrder,
+            syntheticItems)) {
       return OptionalBool.UNKNOWN;
     }
     return OptionalBool.TRUE;
@@ -78,6 +85,7 @@
             initialResolutionHolder,
             context,
             appInfo.getClassToFeatureSplitMap(),
+            appInfo.options(),
             appInfo.getStartupOrder(),
             appInfo.getSyntheticItems());
     if (classAccessibility.isFalse()) {
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index 5b43e8d..94bb52d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -1272,6 +1272,7 @@
                                       clazz,
                                       context,
                                       appInfo.getClassToFeatureSplitMap(),
+                                      appInfo.options(),
                                       appInfo.getStartupOrder(),
                                       appInfo.getSyntheticItems())
                                   .isPossiblyFalse())),
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index de636a8..323c745 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -40,6 +40,7 @@
 import com.android.tools.r8.synthesis.SyntheticFinalization.Result;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import com.android.tools.r8.utils.ConsumerUtils;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.IterableUtils;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.SetUtils;
@@ -544,18 +545,25 @@
 
   private SynthesizingContext getSynthesizingContext(
       ProgramDefinition context, AppView<?> appView) {
+    InternalOptions options = appView.options();
     if (appView.hasClassHierarchy()) {
       AppInfoWithClassHierarchy appInfo = appView.appInfoWithClassHierarchy();
       return getSynthesizingContext(
-          context, appInfo.getClassToFeatureSplitMap(), appInfo.getStartupOrder());
+          context, appInfo.getClassToFeatureSplitMap(), options, appInfo.getStartupOrder());
     }
     return getSynthesizingContext(
-        context, ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap(), StartupOrder.empty());
+        context,
+        ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap(),
+        options,
+        StartupOrder.empty());
   }
 
   /** Used to find the synthesizing context for a new synthetic that is about to be created. */
   private SynthesizingContext getSynthesizingContext(
-      ProgramDefinition context, ClassToFeatureSplitMap featureSplits, StartupOrder startupOrder) {
+      ProgramDefinition context,
+      ClassToFeatureSplitMap featureSplits,
+      InternalOptions options,
+      StartupOrder startupOrder) {
     DexType contextType = context.getContextType();
     SyntheticDefinition<?, ?, ?> existingDefinition = pending.definitions.get(contextType);
     if (existingDefinition != null) {
@@ -571,7 +579,7 @@
           .getContext();
     }
     // This context is not nested in an existing synthetic context so create a new "leaf" context.
-    FeatureSplit featureSplit = featureSplits.getFeatureSplit(context, startupOrder, this);
+    FeatureSplit featureSplit = featureSplits.getFeatureSplit(context, options, startupOrder, this);
     return SynthesizingContext.fromNonSyntheticInputContext(context, featureSplit);
   }
 
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index fbf344b..14b4d67 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -37,7 +37,6 @@
 import com.android.tools.r8.experimental.startup.StartupOrder;
 import com.android.tools.r8.features.ClassToFeatureSplitMap;
 import com.android.tools.r8.features.FeatureSplitConfiguration;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.origin.ArchiveEntryOrigin;
 import com.android.tools.r8.origin.Origin;
@@ -466,7 +465,7 @@
     return programResourcesMainDescriptor.get(resource);
   }
 
-  public void dump(Path output, DumpOptions options, Reporter reporter, DexItemFactory factory) {
+  public void dump(Path output, DumpOptions dumpOptions, InternalOptions options) {
     int nextDexIndex = 0;
     OpenOption[] openOptions =
         new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
@@ -476,26 +475,26 @@
       writeToZipStream(
           out,
           dumpBuildPropertiesFileName,
-          options.getBuildPropertiesFileContent().getBytes(),
+          dumpOptions.getBuildPropertiesFileContent().getBytes(),
           ZipEntry.DEFLATED);
-      if (options.getDesugaredLibraryJsonSource() != null) {
+      if (dumpOptions.getDesugaredLibraryJsonSource() != null) {
         writeToZipStream(
             out,
             dumpDesugaredLibraryFileName,
-            options.getDesugaredLibraryJsonSource().getBytes(),
+            dumpOptions.getDesugaredLibraryJsonSource().getBytes(),
             ZipEntry.DEFLATED);
-        if (options.dumpInputToFile()) {
-          reporter.warning(
+        if (dumpOptions.dumpInputToFile()) {
+          options.reporter.warning(
               "Dumping a compilation with desugared library on a file may prevent reproduction,"
                   + " use dumpInputToDirectory property instead.");
         }
       }
-      if (options.getParsedProguardConfiguration() != null) {
-        String proguardConfig = options.getParsedProguardConfiguration();
+      if (dumpOptions.getParsedProguardConfiguration() != null) {
+        String proguardConfig = dumpOptions.getParsedProguardConfiguration();
         writeToZipStream(out, dumpConfigFileName, proguardConfig.getBytes(), ZipEntry.DEFLATED);
       }
       if (proguardMapInputData != null) {
-        reporter.warning(
+        options.reporter.warning(
             "Dumping proguard map input data may have side effects due to I/O on Paths.");
         writeToZipStream(
             out,
@@ -506,7 +505,7 @@
       if (hasMainDexList()) {
         List<String> mainDexList = new ArrayList<>();
         if (hasMainDexListResources()) {
-          reporter.warning(
+          options.reporter.warning(
               "Dumping main dex list resources may have side effects due to I/O on Paths.");
           for (StringResource mainDexListResource : getMainDexListResources()) {
             mainDexList.add(mainDexListResource.getString());
@@ -518,25 +517,24 @@
         String join = StringUtils.join("\n", mainDexList);
         writeToZipStream(out, dumpMainDexListResourceFileName, join.getBytes(), ZipEntry.DEFLATED);
       }
-      if (options.hasMainDexKeepRules()) {
+      if (dumpOptions.hasMainDexKeepRules()) {
         writeToZipStream(
             out,
             dumpMainDexRulesResourceFileName,
-            StringUtils.joinLines(options.getMainDexKeepRules()).getBytes(),
+            StringUtils.joinLines(dumpOptions.getMainDexKeepRules()).getBytes(),
             ZipEntry.DEFLATED);
       }
       nextDexIndex =
           dumpProgramResources(
               dumpProgramFileName,
-              options.getFeatureSplitConfiguration(),
+              dumpOptions.getFeatureSplitConfiguration(),
               nextDexIndex,
               out,
-              reporter,
-              factory);
+              options);
       nextDexIndex = dumpClasspathResources(nextDexIndex, out);
       nextDexIndex = dumpLibraryResources(nextDexIndex, out);
     } catch (IOException | ResourceException e) {
-      throw reporter.fatalError(new ExceptionDiagnostic(e));
+      throw options.reporter.fatalError(new ExceptionDiagnostic(e));
     }
   }
 
@@ -584,10 +582,8 @@
       FeatureSplitConfiguration featureSplitConfiguration,
       int nextDexIndex,
       ZipOutputStream out,
-      Reporter reporter,
-      DexItemFactory dexItemFactory)
+      InternalOptions options)
       throws IOException, ResourceException {
-
     Map<FeatureSplit, String> featureSplitArchiveNames =
         dumpFeatureSplitFileNames(featureSplitConfiguration);
     Map<FeatureSplit, ByteArrayOutputStream> featureSplitArchiveByteStreams =
@@ -596,7 +592,7 @@
     try {
       ClassToFeatureSplitMap classToFeatureSplitMap =
           ClassToFeatureSplitMap.createInitialClassToFeatureSplitMap(
-              dexItemFactory, featureSplitConfiguration, reporter);
+              options.dexItemFactory(), featureSplitConfiguration, options.reporter);
       if (featureSplitConfiguration != null) {
         for (FeatureSplit featureSplit : featureSplitConfiguration.getFeatureSplits()) {
           ByteArrayOutputStream archiveByteStream = new ByteArrayOutputStream();
@@ -624,11 +620,11 @@
                       nextDexIndex,
                       classDescriptor -> {
                         if (featureSplitConfiguration != null) {
-                          DexType type = dexItemFactory.createType(classDescriptor);
+                          DexType type = options.dexItemFactory().createType(classDescriptor);
                           SyntheticItems syntheticItems = null;
                           FeatureSplit featureSplit =
                               classToFeatureSplitMap.getFeatureSplit(
-                                  type, StartupOrder.empty(), syntheticItems);
+                                  type, options, StartupOrder.empty(), syntheticItems);
                           if (featureSplit != null && !featureSplit.isBase()) {
                             return featureSplitArchiveOutputStreams.get(featureSplit);
                           }
diff --git a/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java b/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java
index 28be79a..4fda093 100644
--- a/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java
+++ b/src/test/java/com/android/tools/r8/AndroidAppDumpsTest.java
@@ -68,7 +68,7 @@
             .build();
 
     Path dumpFile = temp.newFolder().toPath().resolve("dump.zip");
-    appIn.dump(dumpFile, options.dumpOptions, options.reporter, options.dexItemFactory());
+    appIn.dump(dumpFile, options.dumpOptions, options);
 
     AndroidApp appOut = AndroidApp.builder(options.reporter).addDump(dumpFile).build();
     assertEquals(1, appOut.getClassProgramResourcesForTesting().size());