Revert "Record desugar dependencies for interface bridge methods."
This reverts commit b2a9ac6433f10bd1790f1c8a093140bc4d38bd8a.
Reason for revert: broke it all
Change-Id: I606af35669f893668442498aa10279593abfc79d
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 86b2cb8..b9542eb 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.ResolutionResult.IncompatibleClassResult;
import com.android.tools.r8.graph.ResolutionResult.NoSuchMethodResult;
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
-import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
@@ -145,18 +144,6 @@
return app.definitionFor(type);
}
- public DexClass definitionForDesugarDependency(DexClass dependent, DexType type) {
- if (dependent.type == type) {
- return dependent;
- }
- DexClass definition = definitionFor(type);
- if (definition != null && !definition.isLibraryClass() && dependent.isProgramClass()) {
- InterfaceMethodRewriter.reportDependencyEdge(
- dependent.asProgramClass(), definition, options());
- }
- return definition;
- }
-
@Override
public DexProgramClass definitionForProgramType(DexType type) {
return app.programDefinitionFor(type);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index b54bcc9..6fb1c27 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -140,6 +140,14 @@
: closestProgramSubClass);
}
+ public void reportDependency(DexClass clazz, AppView<?> appView) {
+ // If the direct subclass is in the compilation unit, report its dependencies.
+ if (clazz != directSubClass && directSubClass.isProgramClass()) {
+ InterfaceMethodRewriter.reportDependencyEdge(
+ directSubClass.asProgramClass(), clazz, appView);
+ }
+ }
+
public void reportMissingType(DexType missingType, InterfaceMethodRewriter rewriter) {
rewriter.warnMissingInterface(closestProgramSubClass, closestProgramSubClass, missingType);
}
@@ -160,6 +168,11 @@
}
@Override
+ public void reportDependency(DexClass clazz, AppView<?> appView) {
+ // Don't report dependencies in the library.
+ }
+
+ @Override
public void reportMissingType(DexType missingType, InterfaceMethodRewriter rewriter) {
// Ignore missing types in the library.
}
@@ -388,7 +401,7 @@
if (type == null || type == dexItemFactory.objectType) {
return null;
}
- DexClass clazz = appView.appInfo().definitionForDesugarDependency(context.directSubClass, type);
+ DexClass clazz = appView.definitionFor(type);
if (clazz == null) {
context.reportMissingType(type, rewriter);
return null;
@@ -406,6 +419,7 @@
if (clazz.isLibraryClass()) {
return ClassInfo.EMPTY;
}
+ context.reportDependency(clazz, appView);
return classInfo.computeIfAbsent(clazz, key -> visitClassInfoRaw(key, context));
}
@@ -456,6 +470,7 @@
if (iface.isLibraryClass() && ignoreLibraryInfo()) {
return MethodSignatures.EMPTY;
}
+ context.reportDependency(iface, appView);
return interfaceInfo.computeIfAbsent(iface, key -> visitInterfaceInfoRaw(key, context));
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 7f4c043..795755e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -961,7 +961,7 @@
InterfaceProcessor processor = new InterfaceProcessor(appView, this);
for (DexProgramClass clazz : builder.getProgramClasses()) {
if (shouldProcess(clazz, flavour, true)) {
- processor.process(clazz, graphLensBuilder);
+ processor.process(clazz.asProgramClass(), graphLensBuilder);
}
}
for (Entry<DexLibraryClass, Set<DexProgramClass>> entry : requiredDispatchClasses.entrySet()) {
@@ -1114,8 +1114,8 @@
// At this point we likely have a non-library type that may depend on default method information
// from its interfaces and the dependency should be reported.
- if (implementing.isProgramClass() && !definedInterface.isLibraryClass()) {
- reportDependencyEdge(implementing.asProgramClass(), definedInterface, appView.options());
+ if (!definedInterface.isLibraryClass()) {
+ reportDependencyEdge(implementing, definedInterface, appView);
}
// Merge information from all superinterfaces.
@@ -1139,9 +1139,8 @@
}
public static void reportDependencyEdge(
- DexProgramClass dependent, DexClass dependency, InternalOptions options) {
- assert !dependency.isLibraryClass();
- DesugarGraphConsumer consumer = options.desugarGraphConsumer;
+ DexClass dependent, DexClass dependency, AppView<?> appView) {
+ DesugarGraphConsumer consumer = appView.options().desugarGraphConsumer;
if (consumer != null) {
Origin dependentOrigin = dependent.getOrigin();
Origin dependencyOrigin = dependency.getOrigin();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 9599834..787fbe1 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -34,7 +34,6 @@
import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
import com.android.tools.r8.ir.synthetic.SynthesizedCode;
import com.android.tools.r8.origin.SynthesizedOrigin;
-import com.android.tools.r8.utils.Pair;
import com.google.common.collect.BiMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -303,12 +302,6 @@
return true;
}
- private DexClass definitionForDependency(DexType dependency, DexClass dependent) {
- return dependent.isProgramClass()
- ? appView.appInfo().definitionForDesugarDependency(dependent.asProgramClass(), dependency)
- : appView.definitionFor(dependency);
- }
-
// Returns true if the given interface method must be kept on [iface] after moving its
// implementation to the companion class of [iface]. This is always the case for non-bridge
// methods. Bridge methods that does not override an implementation in a super-interface must
@@ -320,33 +313,32 @@
}
}
if (method.accessFlags.isBridge()) {
- Deque<Pair<DexClass, DexType>> worklist = new ArrayDeque<>();
+ Deque<DexType> worklist = new ArrayDeque<>();
Set<DexType> seenBefore = new HashSet<>();
- addSuperTypes(iface, worklist);
+ if (iface.superType != null) {
+ worklist.add(iface.superType);
+ }
+ Collections.addAll(worklist, iface.interfaces.values);
while (!worklist.isEmpty()) {
- Pair<DexClass, DexType> item = worklist.pop();
- DexClass clazz = definitionForDependency(item.getSecond(), item.getFirst());
- if (clazz == null || !seenBefore.add(clazz.type)) {
+ DexType superType = worklist.pop();
+ if (!seenBefore.add(superType)) {
continue;
}
- if (clazz.lookupVirtualMethod(method.method) != null) {
- return false;
+ DexClass clazz = appView.definitionFor(superType);
+ if (clazz != null) {
+ if (clazz.lookupVirtualMethod(method.method) != null) {
+ return false;
+ }
+ if (clazz.superType != null) {
+ worklist.add(clazz.superType);
+ }
+ Collections.addAll(worklist, clazz.interfaces.values);
}
- addSuperTypes(clazz, worklist);
}
}
return true;
}
- private static void addSuperTypes(DexClass clazz, Deque<Pair<DexClass, DexType>> worklist) {
- if (clazz.superType != null) {
- worklist.add(new Pair<>(clazz, clazz.superType));
- }
- for (DexType iface : clazz.interfaces.values) {
- worklist.add(new Pair<>(clazz, iface));
- }
- }
-
private boolean isStaticMethod(DexEncodedMethod method) {
if (method.accessFlags.isNative()) {
throw new Unimplemented("Native interface methods are not yet supported.");
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
deleted file mode 100644
index 2111b7d..0000000
--- a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2019, 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.graph;
-
-import com.android.tools.r8.DesugarGraphConsumer;
-import com.android.tools.r8.origin.Origin;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class DesugarGraphTestConsumer implements DesugarGraphConsumer {
-
- private Map<Origin, Set<Origin>> edges = new HashMap<>();
-
- public boolean contains(Origin dependency, Origin dependent) {
- return edges.getOrDefault(dependency, Collections.emptySet()).contains(dependent);
- }
-
- public int totalEdgeCount() {
- int count = 0;
- for (Set<Origin> dependents : edges.values()) {
- count += dependents.size();
- }
- return count;
- }
-
- @Override
- public synchronized void accept(Origin dependent, Origin dependency) {
- edges.computeIfAbsent(dependency, s -> new HashSet<>()).add(dependent);
- }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java
deleted file mode 100644
index af3c6a0..0000000
--- a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2019, 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.graph;
-
-import com.android.tools.r8.D8TestBuilder;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.origin.Origin;
-import java.io.IOException;
-
-public class DesugarGraphUtils {
-
- public static Origin addClassWithOrigin(Class<?> clazz, D8TestBuilder builder)
- throws IOException {
- Origin origin = makeOrigin(clazz.getTypeName());
- builder.getBuilder().addClassProgramData(ToolHelper.getClassAsBytes(clazz), origin);
- return origin;
- }
-
- private static Origin makeOrigin(String name) {
- return new Origin(Origin.root()) {
- @Override
- public String part() {
- return name;
- }
- };
- }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/InterfaceBridgeDependencyTest.java b/src/test/java/com/android/tools/r8/desugar/graph/InterfaceBridgeDependencyTest.java
deleted file mode 100644
index ec8fcd4..0000000
--- a/src/test/java/com/android/tools/r8/desugar/graph/InterfaceBridgeDependencyTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2019, 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.graph;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import com.android.tools.r8.D8TestBuilder;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.StringUtils;
-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 InterfaceBridgeDependencyTest extends TestBase {
-
- public interface I {
- Object foo();
- }
-
- public interface J extends I {
- // Covariant override of foo will result in a synthetic bridge method and J will depend on I.
- default String foo() {
- return "J::foo";
- }
- }
-
- public interface K extends I {
- // A simple override does not cause a bridge and there is no desugar dependencies for K.
- default Object foo() {
- return "K::foo";
- }
- }
-
- public static class TestClass {
-
- public static void main(String[] args) {
- // There are no instances of I, J or K, so just make sure that the code requires they exist.
- System.out.println(I.class.getName());
- System.out.println(J.class.getName());
- System.out.println(K.class.getName());
- }
- }
-
- // Test runner follows.
-
- private static final String EXPECTED =
- StringUtils.lines(I.class.getName(), J.class.getName(), K.class.getName());
-
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevels().build();
- }
-
- private final TestParameters parameters;
-
- public InterfaceBridgeDependencyTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- @Test
- public void test() throws Exception {
- if (parameters.isCfRuntime()) {
- testForJvm()
- .addProgramClasses(I.class, J.class, K.class, TestClass.class)
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutput(EXPECTED);
- } else {
- D8TestBuilder builder = testForD8();
- DesugarGraphTestConsumer consumer = new DesugarGraphTestConsumer();
- builder.getBuilder().setDesugarGraphConsumer(consumer);
- Origin originI = DesugarGraphUtils.addClassWithOrigin(I.class, builder);
- Origin originJ = DesugarGraphUtils.addClassWithOrigin(J.class, builder);
- Origin originK = DesugarGraphUtils.addClassWithOrigin(K.class, builder);
- builder
- .setMinApi(parameters.getApiLevel())
- .addProgramClasses(TestClass.class)
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutput(EXPECTED);
- // If API level indicates desugaring is needed check the edges are reported.
- if (parameters.getApiLevel().getLevel() < AndroidApiLevel.N.getLevel()) {
- assertTrue(consumer.contains(originI, originJ));
- assertFalse(consumer.contains(originI, originK));
- assertEquals(1, consumer.totalEdgeCount());
- } else {
- assertEquals(0, consumer.totalEdgeCount());
- }
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/InterfaceToImplementingClassDependencyTest.java b/src/test/java/com/android/tools/r8/desugar/graph/InterfaceToImplementingClassDependencyTest.java
index 7f76cad..64044e6 100644
--- a/src/test/java/com/android/tools/r8/desugar/graph/InterfaceToImplementingClassDependencyTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/graph/InterfaceToImplementingClassDependencyTest.java
@@ -4,14 +4,18 @@
package com.android.tools.r8.desugar.graph;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.DesugarGraphConsumer;
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.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -22,7 +26,7 @@
// The simplest program that gives rise to a dependency edge in the graph is an interface with
// an implementing class. In this case, changes to the interface could require re-dexing the
- // implementing class despite no derived changes happening to the classfile for the implementing
+ // implementing class despite no derived changes happing to the classfile for the implementing
// class.
//
// For example, adding default method I.foo will trigger javac compilation of I and A to I.class
@@ -68,24 +72,47 @@
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutputLines("Hello World!");
} else {
- D8TestBuilder builder = testForD8();
- DesugarGraphTestConsumer consumer = new DesugarGraphTestConsumer();
- builder.getBuilder().setDesugarGraphConsumer(consumer);
- Origin originI = DesugarGraphUtils.addClassWithOrigin(I.class, builder);
- Origin originA = DesugarGraphUtils.addClassWithOrigin(A.class, builder);
- builder
- .addProgramClasses(TestClass.class)
+ MyDesugarGraphConsumer consumer = new MyDesugarGraphConsumer();
+ Origin originI = makeOrigin("I");
+ Origin originA = makeOrigin("A");
+ testForD8()
.setMinApi(parameters.getApiLevel())
+ .addProgramClasses(TestClass.class)
+ .apply(
+ b ->
+ b.getBuilder()
+ .setDesugarGraphConsumer(consumer)
+ .addClassProgramData(ToolHelper.getClassAsBytes(I.class), originI)
+ .addClassProgramData(ToolHelper.getClassAsBytes(A.class), originA))
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutputLines("Hello World!");
// If API level indicates desugaring is needed check the edges are reported.
if (parameters.getApiLevel().getLevel() < AndroidApiLevel.N.getLevel()) {
- assertEquals(1, consumer.totalEdgeCount());
- assertTrue(consumer.contains(originI, originA));
+ assertEquals(1, consumer.edges.size());
+ assertEquals(originI, consumer.edges.keySet().iterator().next());
+ assertEquals(originA, consumer.edges.values().iterator().next().iterator().next());
} else {
- assertEquals(0, consumer.totalEdgeCount());
+ assertEquals(0, consumer.edges.size());
}
}
}
+ private Origin makeOrigin(String name) {
+ return new Origin(Origin.root()) {
+ @Override
+ public String part() {
+ return name;
+ }
+ };
+ }
+
+ public static class MyDesugarGraphConsumer implements DesugarGraphConsumer {
+
+ Map<Origin, Set<Origin>> edges = new HashMap<>();
+
+ @Override
+ public synchronized void accept(Origin dependent, Origin dependency) {
+ edges.computeIfAbsent(dependency, s -> new HashSet<>()).add(dependent);
+ }
+ }
}