Trace indirect field accesses from InitClass instructions in repackaging
Bug: 165783399
Change-Id: Ie6e531208cc1046e50c53ad62d8f632a07ac697e
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
index b27182d..57361d3 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
+import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.MemberResolutionResult;
import com.android.tools.r8.graph.ProgramDefinition;
@@ -32,6 +33,7 @@
private final AppInfoWithLiveness appInfo;
private final RepackagingConstraintGraph constraintGraph;
private final ProgramDefinition context;
+ private final InitClassLens initClassLens;
private final RepackagingConstraintGraph.Node node;
public RepackagingUseRegistry(
@@ -42,6 +44,7 @@
this.appInfo = appView.appInfo();
this.constraintGraph = constraintGraph;
this.context = context;
+ this.initClassLens = appView.initClassLens();
this.node = constraintGraph.getNode(context.getDefinition());
}
@@ -145,7 +148,7 @@
@Override
public void registerInitClass(DexType type) {
- registerTypeAccess(type);
+ registerFieldAccess(initClassLens.getInitClassField(type));
}
@Override
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 1ad8f28..de56e20 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -452,10 +452,18 @@
}
public T enableMemberValuePropagationAnnotations() {
- if (!enableMemberValuePropagationAnnotations) {
- enableMemberValuePropagationAnnotations = true;
- addInternalKeepRules(
- "-neverpropagatevalue class * { @com.android.tools.r8.NeverPropagateValue *; }");
+ return enableMemberValuePropagationAnnotations(true);
+ }
+
+ public T enableMemberValuePropagationAnnotations(boolean enable) {
+ if (enable) {
+ if (!enableMemberValuePropagationAnnotations) {
+ enableMemberValuePropagationAnnotations = true;
+ addInternalKeepRules(
+ "-neverpropagatevalue class * { @com.android.tools.r8.NeverPropagateValue *; }");
+ }
+ } else {
+ assert !enableMemberValuePropagationAnnotations;
}
return self();
}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java b/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
index 8eb3d77..c68d18b 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
@@ -62,6 +62,10 @@
return isRepackagedAsExpected(inspector, null, eligibleForRepackaging);
}
+ protected Matcher<Class<?>> isNotRepackaged(CodeInspector inspector) {
+ return isRepackagedAsExpected(inspector, null, false);
+ }
+
/**
* Checks that the class of interest is repackaged as expected.
*
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java
index 9bc8115..e548bcf 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java
@@ -4,23 +4,43 @@
package com.android.tools.r8.repackage;
+import static com.android.tools.r8.shaking.ProguardConfigurationParser.FLATTEN_PACKAGE_HIERARCHY;
+import static com.android.tools.r8.shaking.ProguardConfigurationParser.REPACKAGE_CLASSES;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.NeverPropagateValue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
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 RepackageWithInitClassTest extends RepackageTestBase {
+ private final boolean enableMemberValuePropagationAnnotations;
+
+ @Parameters(name = "{2}, kind: {1}, @NeverPropagateValue: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ BooleanUtils.values(),
+ ImmutableList.of(FLATTEN_PACKAGE_HIERARCHY, REPACKAGE_CLASSES),
+ getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
public RepackageWithInitClassTest(
- String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
+ boolean enableMemberValuePropagationAnnotations,
+ String flattenPackageHierarchyOrRepackageClasses,
+ TestParameters parameters) {
super(flattenPackageHierarchyOrRepackageClasses, parameters);
+ this.enableMemberValuePropagationAnnotations = enableMemberValuePropagationAnnotations;
}
@Test
@@ -30,6 +50,7 @@
.addClassObfuscationDictionary("a")
.addKeepMainRule(TestClass.class)
.apply(this::configureRepackaging)
+ .enableMemberValuePropagationAnnotations(enableMemberValuePropagationAnnotations)
.setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::inspect)
@@ -41,28 +62,45 @@
ClassSubject repackagedClassSubject = inspector.clazz(StaticMemberValuePropagation.class);
assertThat(repackagedClassSubject, isPresent());
- // Verify that a $r8$clinit field was synthesized.
String clinitFieldName = inspector.getFactory().objectMembers.clinitField.name.toSourceString();
- assertThat(repackagedClassSubject.uniqueFieldWithName(clinitFieldName), isPresent());
- assertThat(repackagedClassSubject.uniqueFieldWithName("GREETING"), not(isPresent()));
+ if (enableMemberValuePropagationAnnotations) {
+ // No $r8$clinit field should have been synthesized since we can use the HELLO field.
+ assertThat(repackagedClassSubject.uniqueFieldWithName(clinitFieldName), not(isPresent()));
+ assertThat(repackagedClassSubject.uniqueFieldWithName("HELLO"), isPresent());
- // Verify that the class was repackaged.
- assertThat(StaticMemberValuePropagation.class, isRepackaged(inspector));
+ // Verify that the WORLD field has been removed.
+ assertThat(repackagedClassSubject.uniqueFieldWithName("WORLD"), not(isPresent()));
+
+ // Verify that the class was not repackaged.
+ assertThat(StaticMemberValuePropagation.class, isNotRepackaged(inspector));
+ } else {
+ // Verify that a $r8$clinit field was synthesized.
+ assertThat(repackagedClassSubject.uniqueFieldWithName(clinitFieldName), isPresent());
+
+ // Verify that both fields have been removed.
+ assertThat(repackagedClassSubject.uniqueFieldWithName("HELLO"), not(isPresent()));
+ assertThat(repackagedClassSubject.uniqueFieldWithName("WORLD"), not(isPresent()));
+
+ // Verify that the class was repackaged.
+ assertThat(StaticMemberValuePropagation.class, isRepackaged(inspector));
+ }
}
static class TestClass {
public static void main(String[] args) {
- System.out.println(StaticMemberValuePropagation.GREETING);
+ System.out.println(StaticMemberValuePropagation.WORLD);
}
}
public static class StaticMemberValuePropagation {
- public static String GREETING = " world!";
+ @NeverPropagateValue static String HELLO = "Hello";
+
+ public static String WORLD = " world!";
static {
- System.out.print("Hello");
+ System.out.print(HELLO);
}
}
}