Retain field access information for null valued fields
Change-Id: Ia6ccf06e260453c285d4e5433e4bfb50588529e0
diff --git a/src/main/java/com/android/tools/r8/graph/DexField.java b/src/main/java/com/android/tools/r8/graph/DexField.java
index 1537fb2..e9c2fc5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexField.java
@@ -57,6 +57,11 @@
}
@Override
+ public <T> T apply(Function<DexField, T> fieldConsumer, Function<DexMethod, T> methodConsumer) {
+ return fieldConsumer.apply(this);
+ }
+
+ @Override
public <T> T apply(
Function<DexType, T> classConsumer,
Function<DexField, T> fieldConsumer,
diff --git a/src/main/java/com/android/tools/r8/graph/DexMember.java b/src/main/java/com/android/tools/r8/graph/DexMember.java
index 790fd33..1c02f3b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMember.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMember.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
import com.google.common.collect.Iterables;
+import java.util.function.Function;
public abstract class DexMember<D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
extends DexReference implements NamingLensComparable<R> {
@@ -18,6 +19,9 @@
this.name = name;
}
+ public abstract <T> T apply(
+ Function<DexField, T> fieldConsumer, Function<DexMethod, T> methodConsumer);
+
public abstract DexEncodedMember<?, ?> lookupOnClass(DexClass clazz);
public abstract ProgramMember<?, ?> lookupOnProgramClass(DexProgramClass clazz);
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index 8ab4935..e00c1fe 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -67,6 +67,11 @@
}
@Override
+ public <T> T apply(Function<DexField, T> fieldConsumer, Function<DexMethod, T> methodConsumer) {
+ return methodConsumer.apply(this);
+ }
+
+ @Override
public <T> T apply(
Function<DexType, T> classConsumer,
Function<DexField, T> fieldConsumer,
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 249439c..376abd6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -115,18 +115,21 @@
}
public boolean isAlwaysNull(AppView<AppInfoWithLiveness> appView) {
- if (isClassType()) {
- DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(this));
- if (clazz == null) {
- return false;
- }
- if (appView.options().enableUninstantiatedTypeOptimizationForInterfaces) {
- return !appView.appInfo().isInstantiatedDirectlyOrIndirectly(clazz);
- } else {
- return !clazz.isInterface() && !appView.appInfo().isInstantiatedDirectlyOrIndirectly(clazz);
- }
+ return isAlwaysNull(appView.appInfo());
+ }
+
+ public boolean isAlwaysNull(AppInfoWithLiveness appInfo) {
+ if (!isClassType()) {
+ return false;
}
- return false;
+ DexProgramClass clazz = asProgramClassOrNull(appInfo.definitionFor(this));
+ if (clazz == null) {
+ return false;
+ }
+ if (appInfo.options().enableUninstantiatedTypeOptimizationForInterfaces) {
+ return !appInfo.isInstantiatedDirectlyOrIndirectly(clazz);
+ }
+ return !clazz.isInterface() && !appInfo.isInstantiatedDirectlyOrIndirectly(clazz);
}
public boolean isSamePackage(DexType other) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 615e5ae..39ce729 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -360,7 +360,9 @@
}
AbstractValue abstractValue;
- if (appView.appInfo().isFieldWrittenByFieldPutInstruction(target)) {
+ if (field.getType().isAlwaysNull(appView)) {
+ abstractValue = appView.abstractValueFactory().createSingleNumberValue(0);
+ } else if (appView.appInfo().isFieldWrittenByFieldPutInstruction(target)) {
abstractValue = target.getOptimizationInfo().getAbstractValue();
if (abstractValue.isUnknown() && !target.isStatic()) {
AbstractValue abstractReceiverValue =
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index c681eaa..d60ba25 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -14,8 +14,6 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.FieldAccessInfo;
-import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
@@ -97,18 +95,11 @@
public UninstantiatedTypeOptimization strenghtenOptimizationInfo() {
OptimizationFeedback feedback = OptimizationFeedbackSimple.getInstance();
- FieldAccessInfoCollection<?> fieldAccessInfoCollection =
- appView.appInfo().getFieldAccessInfoCollection();
AbstractValue nullValue = appView.abstractValueFactory().createSingleNumberValue(0);
for (DexProgramClass clazz : appView.appInfo().classes()) {
clazz.forEachField(
field -> {
if (field.type().isAlwaysNull(appView)) {
- FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(field.field);
- if (fieldAccessInfo != null) {
- // Clear all writes since each write must write `null` to the field.
- fieldAccessInfo.asMutable().clearWrites();
- }
feedback.recordFieldHasAbstractValue(field, appView, nullValue);
}
});
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index e12ec89..855e24c 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -839,11 +839,31 @@
&& !keepInfo.getMethodInfo(method).isPinned();
}
- public boolean mayPropagateValueFor(DexReference reference) {
+ public boolean mayPropagateValueFor(DexMember<?, ?> reference) {
assert checkIfObsolete();
- return options().enableValuePropagation
- && !isPinned(reference)
- && !neverPropagateValue.contains(reference);
+ return reference.apply(this::mayPropagateValueFor, this::mayPropagateValueFor);
+ }
+
+ public boolean mayPropagateValueFor(DexField field) {
+ assert checkIfObsolete();
+ if (!options().enableValuePropagation || neverPropagateValue.contains(field)) {
+ return false;
+ }
+ if (isPinned(field) && !field.getType().isAlwaysNull(this)) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean mayPropagateValueFor(DexMethod method) {
+ assert checkIfObsolete();
+ if (!options().enableValuePropagation || neverPropagateValue.contains(method)) {
+ return false;
+ }
+ if (isPinned(method) && !method.getReturnType().isAlwaysNull(this)) {
+ return false;
+ }
+ return true;
}
private boolean isLibraryOrClasspathField(DexEncodedField field) {
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
index c43c289..689e080 100644
--- a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
@@ -25,7 +25,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.Calendar;
import java.util.List;
import java.util.TreeSet;
@@ -46,11 +45,12 @@
protected abstract List<Class<?>> getMethodTemplateClasses();
- public static String getHeaderString(Class<?> generationClass, String generatedPackage) {
- int year = Calendar.getInstance().get(Calendar.YEAR);
- String simpleName = generationClass.getSimpleName();
+ protected abstract int getYear();
+
+ public String getHeaderString() {
+ String simpleName = getClass().getSimpleName();
return StringUtils.lines(
- "// Copyright (c) " + year + ", the R8 project authors. Please see the AUTHORS file",
+ "// Copyright (c) " + getYear() + ", 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.",
"",
@@ -58,7 +58,7 @@
"// GENERATED FILE. DO NOT EDIT! See " + simpleName + ".java.",
"// ***********************************************************************************",
"",
- "package " + generatedPackage + ";");
+ "package " + getGeneratedClassPackageName() + ";");
}
protected Path getGeneratedFile() {
@@ -115,7 +115,7 @@
private void generateRawOutput(CfCodePrinter codePrinter, Path tempFile) throws IOException {
try (PrintStream printer = new PrintStream(Files.newOutputStream(tempFile))) {
- printer.print(getHeaderString(this.getClass(), getGeneratedClassPackageName()));
+ printer.print(getHeaderString());
printer.println("import com.android.tools.r8.graph.DexItemFactory;");
codePrinter.getImports().forEach(i -> printer.println("import " + i + ";"));
printer.println("public final class " + getGeneratedClassName() + " {\n");
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java b/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java
index 54a405c..74bf88f 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java
@@ -50,6 +50,10 @@
return METHOD_TEMPLATE_CLASSES;
}
+ @Override
+ protected int getYear() {
+ return 2020;
+ }
@Test
public void testEnumUtilityMethodsGenerated() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
index 05c11c4..d78a1c7 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
@@ -68,6 +68,11 @@
return METHOD_TEMPLATE_CLASSES;
}
+ @Override
+ protected int getYear() {
+ return 2020;
+ }
+
@Test
public void testBackportsGenerated() throws Exception {
ArrayList<Class<?>> sorted = new ArrayList<>(getMethodTemplateClasses());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/templates/GenerateCfUtilityMethodsForCodeOptimizations.java b/src/test/java/com/android/tools/r8/ir/optimize/templates/GenerateCfUtilityMethodsForCodeOptimizations.java
index c35135e..732952d 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/templates/GenerateCfUtilityMethodsForCodeOptimizations.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/templates/GenerateCfUtilityMethodsForCodeOptimizations.java
@@ -43,6 +43,11 @@
return ImmutableList.of(CfUtilityMethodsForCodeOptimizationsTemplates.class);
}
+ @Override
+ protected int getYear() {
+ return 2020;
+ }
+
@Test
public void test() throws Exception {
ArrayList<Class<?>> sorted = new ArrayList<>(getMethodTemplateClasses());