Allow vertical class merging even when inlining is disabled
Change-Id: Ie3fbb32f62f50303c9a0e14a583514cd622662fd
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 215ced9..320180e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -369,11 +369,11 @@
timing.end();
}
appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
- // Class merging requires inlining.
- if (options.enableClassMerging && options.enableInlining) {
+ if (options.enableClassMerging) {
timing.begin("ClassMerger");
VerticalClassMerger classMerger =
- new VerticalClassMerger(application, appViewWithLiveness, executorService, timing);
+ new VerticalClassMerger(
+ application, appViewWithLiveness, executorService, options, timing);
appView.setGraphLense(classMerger.run());
timing.end();
application = application.asDirect().rewrittenWithLense(appView.getGraphLense());
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 8dec498..3e4700c 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -39,6 +39,7 @@
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.FieldSignatureEquivalence;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.Equivalence;
@@ -163,6 +164,7 @@
private final ExecutorService executorService;
private final GraphLense graphLense;
private final MethodPoolCollection methodPoolCollection;
+ private final InternalOptions options;
private final Timing timing;
private Collection<DexMethod> invokes;
@@ -185,12 +187,14 @@
DexApplication application,
AppView<AppInfoWithLiveness> appView,
ExecutorService executorService,
+ InternalOptions options,
Timing timing) {
this.application = application;
this.appInfo = appView.getAppInfo();
this.executorService = executorService;
this.graphLense = appView.getGraphLense();
this.methodPoolCollection = new MethodPoolCollection(application);
+ this.options = options;
this.renamedMembersLense = new VerticalClassMergerGraphLense.Builder();
this.timing = timing;
@@ -1494,20 +1498,20 @@
}
private boolean disallowInlining(DexEncodedMethod method, DexType invocationContext) {
- // TODO(christofferqa): Determine the situations where markForceInline() may fail, and ensure
- // that we always return true here in these cases.
- if (method.getCode().isJarCode()) {
- JarCode jarCode = method.getCode().asJarCode();
- ConstraintWithTarget constraint =
- jarCode.computeInliningConstraint(
- method,
- appInfo,
- new SingleTypeMapperGraphLense(method.method.holder, invocationContext),
- invocationContext);
- return constraint == ConstraintWithTarget.NEVER;
+ if (options.enableInlining) {
+ if (method.getCode().isJarCode()) {
+ JarCode jarCode = method.getCode().asJarCode();
+ ConstraintWithTarget constraint =
+ jarCode.computeInliningConstraint(
+ method,
+ appInfo,
+ new SingleTypeMapperGraphLense(method.method.holder, invocationContext),
+ invocationContext);
+ return constraint == ConstraintWithTarget.NEVER;
+ }
+ // TODO(christofferqa): For non-jar code we currently cannot guarantee that markForceInline()
+ // will succeed.
}
- // TODO(christofferqa): For non-jar code we currently cannot guarantee that markForceInline()
- // will succeed.
return true;
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 2a56ef5..aad109a 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -262,6 +262,31 @@
}
@Test
+ public void testMergeInterfaceWithoutInlining() throws Throwable {
+ String main = "classmerging.ConflictingInterfaceSignaturesTest";
+ Path[] programFiles =
+ new Path[] {
+ CF_DIR.resolve("ConflictingInterfaceSignaturesTest.class"),
+ CF_DIR.resolve("ConflictingInterfaceSignaturesTest$A.class"),
+ CF_DIR.resolve("ConflictingInterfaceSignaturesTest$B.class"),
+ CF_DIR.resolve("ConflictingInterfaceSignaturesTest$InterfaceImpl.class")
+ };
+ Set<String> preservedClassNames =
+ ImmutableSet.of(
+ "classmerging.ConflictingInterfaceSignaturesTest",
+ "classmerging.ConflictingInterfaceSignaturesTest$InterfaceImpl");
+ runTestOnInput(
+ main,
+ readProgramFiles(programFiles),
+ preservedClassNames::contains,
+ getProguardConfig(EXAMPLE_KEEP),
+ options -> {
+ this.configure(options);
+ options.enableInlining = false;
+ });
+ }
+
+ @Test
public void testMethodCollision() throws Throwable {
String main = "classmerging.MethodCollisionTest";
Path[] programFiles =