Version 1.4.31
Cherry pick: Also consider targeted methods for if-rule evaluation
CL: https://r8-review.googlesource.com/c/r8/+/33489
Bug: 122940365
Change-Id: I9b6db08b1852dd730e7f334f642251deadd0d074
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 115fe4a..cf756ef 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 = "1.4.30";
+ public static final String LABEL = "1.4.31";
private Version() {
}
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 86a4a8d..0761a71 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1460,7 +1460,10 @@
new RootSetBuilder(appView, rootSet.ifRules, options);
IfRuleEvaluator ifRuleEvaluator =
consequentSetBuilder.getIfRuleEvaluator(
- liveMethods.getItems(), liveFields.getItems(), executorService);
+ liveFields.getItems(),
+ liveMethods.getItems(),
+ targetedMethods.getItems(),
+ executorService);
ConsequentRootSet consequentRootSet = ifRuleEvaluator.run(liveTypes);
enqueueRootItems(consequentRootSet.noShrinking);
rootSet.neverInline.addAll(consequentRootSet.neverInline);
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index a0da9e7..2a8ce8f 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -277,26 +277,31 @@
}
IfRuleEvaluator getIfRuleEvaluator(
- Set<DexEncodedMethod> liveMethods,
Set<DexEncodedField> liveFields,
+ Set<DexEncodedMethod> liveMethods,
+ Set<DexEncodedMethod> targetedMethods,
ExecutorService executorService) {
- return new IfRuleEvaluator(liveMethods, liveFields, executorService);
+ return new IfRuleEvaluator(liveFields, liveMethods, targetedMethods, executorService);
}
class IfRuleEvaluator {
- private final Set<DexEncodedMethod> liveMethods;
private final Set<DexEncodedField> liveFields;
+ private final Set<DexEncodedMethod> liveMethods;
+ private final Set<DexEncodedMethod> targetedMethods;
+
private final ExecutorService executorService;
private final List<Future<?>> futures = new ArrayList<>();
public IfRuleEvaluator(
- Set<DexEncodedMethod> liveMethods,
Set<DexEncodedField> liveFields,
+ Set<DexEncodedMethod> liveMethods,
+ Set<DexEncodedMethod> targetedMethods,
ExecutorService executorService) {
- this.liveMethods = liveMethods;
this.liveFields = liveFields;
+ this.liveMethods = liveMethods;
+ this.targetedMethods = targetedMethods;
this.executorService = executorService;
}
@@ -391,7 +396,7 @@
filteredMembers,
targetClass.methods(
m ->
- liveMethods.contains(m)
+ (liveMethods.contains(m) || targetedMethods.contains(m))
&& appView.graphLense().getOriginalMethodSignature(m.method).getHolder()
== sourceClass.type));
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java
new file mode 100644
index 0000000..edf2b89
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java
@@ -0,0 +1,68 @@
+// 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.shaking.ifrule;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.lang.reflect.Proxy;
+import org.junit.Test;
+
+public class IfOnTargetedMethodTest extends TestBase {
+
+ @Test
+ public void test() throws Exception {
+ String expectedOutput = StringUtils.lines("Hello world!");
+
+ testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expectedOutput);
+
+ CodeInspector inspector =
+ testForR8(Backend.DEX)
+ .addInnerClasses(IfOnTargetedMethodTest.class)
+ .addKeepMainRule(TestClass.class)
+ .addKeepRules(
+ "-if interface * { @" + MyAnnotation.class.getTypeName() + " <methods>; }",
+ "-keep,allowobfuscation interface <1>")
+ .run(TestClass.class)
+ .assertSuccessWithOutput(expectedOutput)
+ .inspector();
+
+ ClassSubject interfaceSubject = inspector.clazz(Interface.class);
+ assertThat(interfaceSubject, isPresent());
+ assertThat(interfaceSubject, isRenamed());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ Interface obj = getInstance();
+ obj.method();
+ }
+
+ static Interface getInstance() {
+ return (Interface)
+ Proxy.newProxyInstance(
+ Interface.class.getClassLoader(),
+ new Class[] {Interface.class},
+ (o, method, objects) -> {
+ System.out.println("Hello world!");
+ return null;
+ });
+ }
+ }
+
+ interface Interface {
+
+ @MyAnnotation
+ void method();
+ }
+
+ @interface MyAnnotation {}
+}