Version 1.0.13.
Merge: Include catched types as direct dependencies (Bug: 74105749)
CL: https://r8-review.googlesource.com/c/r8/+/17160
Change-Id: I8e975260370d33f90a606595c377b585932d8018
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 9781dc5..5ea4f5f 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "v1.0.12";
+ public static final String LABEL = "v1.0.13";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index f7c3b24..a9b3c9e 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.utils.InternalOptions;
import java.util.Collections;
import java.util.List;
+import java.util.function.Consumer;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -154,7 +155,12 @@
}
@Override
- public void registerReachableDefinitions(UseRegistry registry) {
+ public void registerInstructionsReferences(UseRegistry registry) {
+ throw new Unimplemented("Inspecting Java class-file bytecode not yet supported");
+ }
+
+ @Override
+ public void registerCaughtTypes(Consumer<DexType> dexTypeConsumer) {
throw new Unimplemented("Inspecting Java class-file bytecode not yet supported");
}
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 14c4bbc..b6c1583 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.ir.optimize.Outliner.OutlineCode;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.InternalOptions;
+import java.util.function.Consumer;
public abstract class Code extends CachedHashValueDexItem {
@@ -29,7 +30,9 @@
+ getClass().getCanonicalName());
}
- public abstract void registerReachableDefinitions(UseRegistry registry);
+ public abstract void registerInstructionsReferences(UseRegistry registry);
+
+ public abstract void registerCaughtTypes(Consumer<DexType> dexTypeConsumer);
@Override
public abstract String toString();
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index a522e82..1517dfb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
@@ -27,6 +28,7 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
// DexCode corresponds to code item in dalvik/dex-format.html
public class DexCode extends Code {
@@ -188,13 +190,22 @@
}
@Override
- public void registerReachableDefinitions(UseRegistry registry) {
+ public void registerInstructionsReferences(UseRegistry registry) {
for (Instruction insn : instructions) {
insn.registerUse(registry);
}
}
@Override
+ public void registerCaughtTypes(Consumer<DexType> dexTypeConsumer) {
+ for (TryHandler handler : handlers) {
+ for (TypeAddrPair pair : handler.pairs) {
+ dexTypeConsumer.accept(pair.type);
+ }
+ }
+ }
+
+ @Override
public String toString() {
return toString(null, null);
}
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 4a903dc..6a7726f 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -501,12 +501,21 @@
return !annotations.isEmpty() || !parameterAnnotations.isEmpty();
}
- public void registerReachableDefinitions(UseRegistry registry) {
+ public void registerInstructionsReferences(UseRegistry registry) {
if (code != null) {
if (Log.ENABLED) {
Log.verbose(getClass(), "Registering definitions reachable from `%s`.", method);
}
- code.registerReachableDefinitions(registry);
+ code.registerInstructionsReferences(registry);
+ }
+ }
+
+ public void registerCatchedTypes(Consumer<DexType> dexTypeConsumer) {
+ if (code != null) {
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Visiting catched types `%s`.", method);
+ }
+ code.registerCaughtTypes(dexTypeConsumer);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/JarCode.java b/src/main/java/com/android/tools/r8/graph/JarCode.java
index 62dc43f..11a70a3 100644
--- a/src/main/java/com/android/tools/r8/graph/JarCode.java
+++ b/src/main/java/com/android/tools/r8/graph/JarCode.java
@@ -13,11 +13,13 @@
import com.android.tools.r8.jar.JarRegisterEffectsVisitor;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
@@ -148,13 +150,20 @@
}
@Override
- public void registerReachableDefinitions(UseRegistry registry) {
+ public void registerInstructionsReferences(UseRegistry registry) {
triggerDelayedParsingIfNeccessary();
node.instructions.accept(
new JarRegisterEffectsVisitor(method.getHolder(), registry, application));
}
@Override
+ public void registerCaughtTypes(Consumer<DexType> dexTypeConsumer) {
+ node.tryCatchBlocks.forEach(tryCatchBlockNode ->
+ dexTypeConsumer.accept(application.getTypeFromDescriptor(
+ DescriptorUtils.getDescriptorFromClassBinaryName(tryCatchBlockNode.type))));
+ }
+
+ @Override
public String toString() {
triggerDelayedParsingIfNeccessary();
TraceMethodVisitor visitor = new TraceMethodVisitor(new Textifier());
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
index b2dafdd..f863778 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
@@ -144,7 +144,7 @@
for (DexEncodedMethod method : clazz.allMethodsSorted()) {
Node node = graph.ensureMethodNode(method);
InvokeExtractor extractor = new InvokeExtractor(appInfo, graphLense, node, graph);
- method.registerReachableDefinitions(extractor);
+ method.registerInstructionsReferences(extractor);
}
}
assert allMethodsExists(application, graph);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index e834b61..536e4b7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -62,6 +62,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.function.Consumer;
public class Outliner {
@@ -1009,7 +1010,12 @@
}
@Override
- public void registerReachableDefinitions(UseRegistry registry) {
+ public void registerInstructionsReferences(UseRegistry registry) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public void registerCaughtTypes(Consumer<DexType> dexTypeConsumer) {
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
index 0de034a..26ef333 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -47,11 +48,18 @@
}
@Override
- public void registerReachableDefinitions(UseRegistry registry) {
+ public void registerInstructionsReferences(UseRegistry registry) {
registryCallback.accept(registry);
}
@Override
+ public void registerCaughtTypes(Consumer<DexType> dexTypeConsumer) {
+ // Support for synthesized code with catch handler is not implemented.
+ // Let's check that we're in a well known where no catch handler is possible.
+ assert sourceCode.instructionCount() == 1 || sourceCode instanceof SingleBlockSourceCode;
+ }
+
+ @Override
protected final int computeHashCode() {
return sourceCode.hashCode();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java b/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java
index a915849..321001e 100644
--- a/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java
@@ -38,7 +38,7 @@
// be removed.
if (method.accessFlags.isBridge() && !method.accessFlags.isAbstract()) {
InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor();
- method.getCode().registerReachableDefinitions(targetExtractor);
+ method.getCode().registerInstructionsReferences(targetExtractor);
DexMethod target = targetExtractor.getTarget();
InvokeKind kind = targetExtractor.getKind();
if (target != null && target.getArity() == method.method.getArity()) {
diff --git a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
index 7f5a4f3..685e733 100644
--- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
@@ -30,7 +30,7 @@
private void identifyBridgeMethod(DexEncodedMethod method) {
if (method.accessFlags.isBridge()) {
InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor();
- method.getCode().registerReachableDefinitions(targetExtractor);
+ method.getCode().registerInstructionsReferences(targetExtractor);
DexMethod target = targetExtractor.getTarget();
InvokeKind kind = targetExtractor.getKind();
if (target != null &&
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 0bd3068..9aff920 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1119,7 +1119,7 @@
if (protoLiteExtension != null && protoLiteExtension.appliesTo(method)) {
protoLiteExtension.processMethod(method, new UseRegistry(method), protoLiteFields);
} else {
- method.registerReachableDefinitions(new UseRegistry(method));
+ method.registerInstructionsReferences(new UseRegistry(method));
}
// Add all dependent members to the workqueue.
enqueueRootItems(rootSet.getDependentItems(method));
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
index f8b54ab..de21187 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -151,7 +151,8 @@
clazz.forEachField(field -> addMainDexType(field.field.type));
clazz.forEachMethod(method -> {
traceMethodDirectDependencies(method.method);
- method.registerReachableDefinitions(codeDirectReferenceCollector);
+ method.registerInstructionsReferences(codeDirectReferenceCollector);
+ method.registerCatchedTypes(this::addMainDexType);
});
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
index 02159cf..63475b7 100644
--- a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
@@ -371,7 +371,7 @@
return existing;
} else if (existing.accessFlags.isBridge()) {
InvokeSingleTargetExtractor extractor = new InvokeSingleTargetExtractor();
- existing.getCode().registerReachableDefinitions(extractor);
+ existing.getCode().registerInstructionsReferences(extractor);
if (extractor.getTarget() != method.method) {
abortMerge = true;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
index 8049bf4..c2ba7e5 100644
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
+++ b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
@@ -116,13 +116,13 @@
// serialized stream for this proto. As we mask all reads in the writing code and normally
// remove fields that are only written but never read, we have to mark fields used in setters
// as read and written.
- method.registerReachableDefinitions(
+ method.registerInstructionsReferences(
new FieldWriteImpliesReadUseRegistry(registry, method.method.holder));
} else {
// Filter all getters and field accesses in these methods. We do not want fields to become
// live just due to being referenced in a special method. The pruning phase will remove
// all references to dead fields in the code later.
- method.registerReachableDefinitions(new FilteringUseRegistry(registry, method.method.holder,
+ method.registerInstructionsReferences(new FilteringUseRegistry(registry, method.method.holder,
protoLiteFields));
}
}
diff --git a/src/test/examples/multidex006/ClassForMainDex.java b/src/test/examples/multidex006/ClassForMainDex.java
new file mode 100644
index 0000000..86c2e9a
--- /dev/null
+++ b/src/test/examples/multidex006/ClassForMainDex.java
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, 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 multidex006;
+
+/**
+ * Class directly referenced from Activity, will be kept in main dex. The class is not referenced
+ * by <clinit> or <init>, its direct references are not kept in main dex.
+ */
+public class ClassForMainDex {
+
+ public static void method1() {
+ try {
+ doNothing();
+ } catch (NotThrownException e) {
+ // ignore
+ }
+ }
+
+ public static void doNothing() {
+
+ }
+
+}
diff --git a/src/test/examples/multidex006/NotThrownException.java b/src/test/examples/multidex006/NotThrownException.java
new file mode 100644
index 0000000..4aa5e6c
--- /dev/null
+++ b/src/test/examples/multidex006/NotThrownException.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, 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 multidex006;
+
+public class NotThrownException extends RuntimeException {
+}
diff --git a/src/test/examples/multidex006/main-dex-rules-1.txt b/src/test/examples/multidex006/main-dex-rules-1.txt
new file mode 100644
index 0000000..333d866
--- /dev/null
+++ b/src/test/examples/multidex006/main-dex-rules-1.txt
@@ -0,0 +1,6 @@
+# Copyright (c) 2018, 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.
+
+-keep public class *.ClassForMainDex {
+}
\ No newline at end of file
diff --git a/src/test/examples/multidex006/ref-list-1.txt b/src/test/examples/multidex006/ref-list-1.txt
new file mode 100644
index 0000000..b39deba
--- /dev/null
+++ b/src/test/examples/multidex006/ref-list-1.txt
@@ -0,0 +1,2 @@
+Lmultidex006/ClassForMainDex;
+Lmultidex006/NotThrownException;
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
index 8b143da..19aaaef 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
@@ -124,6 +124,17 @@
doTest5(6);
}
+ @Test
+ public void traceMainDexList006() throws Throwable {
+ doTest(
+ "traceMainDexList006",
+ "multidex006",
+ EXAMPLE_BUILD_DIR,
+ Paths.get(EXAMPLE_SRC_DIR, "multidex006", "main-dex-rules-1.txt"),
+ Paths.get(EXAMPLE_SRC_DIR, "multidex006", "ref-list-1.txt"),
+ AndroidApiLevel.I);
+ }
+
private void doTest5(int variant) throws Throwable {
doTest(
"traceMainDexList003",
@@ -211,9 +222,15 @@
int nonLambdaOffset = 0;
for (int i = 0; i < refList.length; i++) {
String reference = refList[i].trim();
+ if (r8MainDexList.size() <= i) {
+ Assert.fail("R8 main dex list is missing '" + reference + "'");
+ }
checkSameMainDexEntry(reference, r8MainDexList.get(i));
// The main dex list generator does not do any lambda desugaring.
if (!isLambda(reference)) {
+ if (mainDexGeneratorMainDexList.size() <= i - nonLambdaOffset) {
+ Assert.fail("Main dex list generator is missing '" + reference + "'");
+ }
checkSameMainDexEntry(reference, mainDexGeneratorMainDexList.get(i - nonLambdaOffset));
} else {
nonLambdaOffset++;