Improve logging in type propagation
Change-Id: I51d1cf307f05e9269919f8a89cd58f705b14e128
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicTypeWithUpperBound.java b/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicTypeWithUpperBound.java
index 68777ec..2c9fc11 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicTypeWithUpperBound.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicTypeWithUpperBound.java
@@ -269,7 +269,19 @@
@Override
public String toString() {
- return "DynamicTypeWithUpperBound(upperBound=" + getDynamicUpperBoundType() + ")";
+ if (isBottom()) {
+ return "BottomDynamicType";
+ }
+ if (isNotNullType()) {
+ return "NotNullDynamicType";
+ }
+ if (isNullType()) {
+ return "NullDynamicType";
+ }
+ if (isUnknown()) {
+ return "UnknownDynamicType";
+ }
+ return "DynamicTypeWithUpperBound(" + getDynamicUpperBoundType() + ")";
}
private static boolean verifyNotEffectivelyFinalClassType(
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ExactDynamicType.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ExactDynamicType.java
index 816388f..b620d4c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ExactDynamicType.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ExactDynamicType.java
@@ -77,6 +77,6 @@
@Override
public String toString() {
- return "ExactDynamicType(type=" + getExactClassType() + ")";
+ return "ExactDynamicType(" + getExactClassType() + ")";
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java
index e735de5..8987509 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/StatefulObjectValue.java
@@ -68,7 +68,7 @@
@Override
public String toString() {
- return "StatefulValue";
+ return "StatefulValue(" + state + ")";
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EmptyObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EmptyObjectState.java
index d16e2b0..110e009 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EmptyObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/EmptyObjectState.java
@@ -52,4 +52,9 @@
public int hashCode() {
return System.identityHashCode(this);
}
+
+ @Override
+ public String toString() {
+ return "EmptyObjectState";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java
index a773fd2..ca07bf0 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/KnownLengthArrayState.java
@@ -60,4 +60,9 @@
public int hashCode() {
return System.identityHashCode(this);
}
+
+ @Override
+ public String toString() {
+ return "KnownLengthArrayState(" + length + ")";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/NonEmptyObjectState.java b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/NonEmptyObjectState.java
index 7acebdd..cc3f212 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/NonEmptyObjectState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/objectstate/NonEmptyObjectState.java
@@ -10,7 +10,11 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.util.ArrayList;
import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
@@ -78,4 +82,15 @@
public int hashCode() {
return state.hashCode();
}
+
+ @Override
+ public String toString() {
+ List<DexField> sortedKeys = ListUtils.sort(state.keySet(), DexField::compareTo);
+ List<String> data = new ArrayList<>();
+ for (DexField key : sortedKeys) {
+ AbstractValue abstractValue = state.get(key);
+ data.add(key.toSourceString() + " -> " + abstractValue);
+ }
+ return "ObjectState(" + StringUtils.join(", ", data) + ")";
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java
index 7b390d6..852bd2b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/AbstractFunction.java
@@ -42,6 +42,10 @@
*/
Iterable<BaseInFlow> getBaseInFlow();
+ default boolean hasSingleInFlow() {
+ return true;
+ }
+
@Override
default boolean isAbstractFunction() {
return true;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FlowGraphStateProvider.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FlowGraphStateProvider.java
index 764c7f4..fce1a27 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FlowGraphStateProvider.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FlowGraphStateProvider.java
@@ -17,10 +17,11 @@
}
// If the abstract function is a canonical function, or the abstract function has a single
// declared input, we should never perform any state lookups.
- if (abstractFunction.isIdentity()
- || abstractFunction.isCastAbstractFunction()
- || abstractFunction.isUnknownAbstractFunction()
- || abstractFunction.isUpdateChangedFlagsAbstractFunction()) {
+ if (abstractFunction.hasSingleInFlow()) {
+ assert abstractFunction.isIdentity()
+ || abstractFunction.isCastAbstractFunction()
+ || abstractFunction.isUnknownAbstractFunction()
+ || abstractFunction.isUpdateChangedFlagsAbstractFunction();
return new FlowGraphStateProvider() {
@Override
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InFlow.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InFlow.java
index ab8aed4..3c071be 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InFlow.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InFlow.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.optimize.argumentpropagation.codescanner;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.optimize.compose.UpdateChangedFlagsAbstractFunction;
public interface InFlow {
@@ -56,6 +57,10 @@
return false;
}
+ default boolean isMethodParameter(DexMethod method, int parameterIndex) {
+ return false;
+ }
+
default MethodParameter asMethodParameter() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
index 1993257..366dea4 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/InstanceFieldReadAbstractFunction.java
@@ -63,6 +63,11 @@
}
@Override
+ public boolean hasSingleInFlow() {
+ return false;
+ }
+
+ @Override
public boolean isInstanceFieldReadAbstractFunction() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java
index 7ebb2d0..b8481e4 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameter.java
@@ -47,6 +47,11 @@
}
@Override
+ public boolean isMethodParameter(DexMethod method, int parameterIndex) {
+ return this.method.isIdenticalTo(method) && this.index == parameterIndex;
+ }
+
+ @Override
public MethodParameter asMethodParameter() {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java
index d65a397..04ec003 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphFieldNode.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.BaseInFlow;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
public class FlowGraphFieldNode extends FlowGraphNode {
@@ -22,6 +23,11 @@
}
@Override
+ boolean equalsBaseInFlow(BaseInFlow inFlow) {
+ return inFlow.isFieldValue(field.getReference());
+ }
+
+ @Override
DexType getStaticType() {
return field.getType();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java
index ba8f33b..7e9e448 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphNode.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.AbstractFunction;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.BaseInFlow;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteValueState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.StateCloner;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
@@ -53,6 +54,8 @@
}
}
+ abstract boolean equalsBaseInFlow(BaseInFlow inFlow);
+
boolean getDebug() {
return debug;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
index 555e6c8..0bf105a 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphParameterNode.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.BaseInFlow;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodParameter;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
@@ -34,6 +35,11 @@
}
@Override
+ boolean equalsBaseInFlow(BaseInFlow inFlow) {
+ return inFlow.isMethodParameter(method.getReference(), parameterIndex);
+ }
+
+ @Override
DexType getStaticType() {
return parameterType;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
index 67f7f65..2cdcf24 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagator.java
@@ -256,7 +256,8 @@
state,
transferFunction,
transferState,
- oldSuccessorStateForDebugging);
+ oldSuccessorStateForDebugging,
+ flowGraphStateProvider);
// If this successor has become unknown, there is no point in continuing to propagate
// flow to it from any of its predecessors. We therefore clear the predecessors to
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
index d7f38d8..e17e5b6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/InFlowPropagatorDebugUtils.java
@@ -6,9 +6,13 @@
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.AbstractFunction;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.BaseInFlow;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteValueState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.FlowGraphStateProvider;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.WorkList;
+import java.util.ArrayList;
import java.util.List;
public class InFlowPropagatorDebugUtils {
@@ -76,18 +80,37 @@
ConcreteValueState nodeStateAfterNarrowing,
AbstractFunction transferFunction,
ValueState transferState,
- ValueState oldSuccessorState) {
+ ValueState oldSuccessorState,
+ FlowGraphStateProvider flowGraphStateProvider) {
if (successorNode.getDebug()) {
+ List<String> transferFunctionDependencies = new ArrayList<>();
+ if (!transferFunction.hasSingleInFlow()) {
+ transferFunctionDependencies.add("");
+ transferFunctionDependencies.add("TRANSFER FN INPUTS:");
+ for (BaseInFlow transferFunctionDependency : transferFunction.getBaseInFlow()) {
+ if (!node.equalsBaseInFlow(transferFunctionDependency)) {
+ ValueState transferFunctionDependencyState =
+ flowGraphStateProvider.getState(transferFunctionDependency, null);
+ transferFunctionDependencies.add(" DEP: " + transferFunctionDependency);
+ transferFunctionDependencies.add(" DEP STATE: " + transferFunctionDependencyState);
+ }
+ }
+ }
+ ValueState newSuccessorState = successorNode.getState();
log(
"PROPAGATE CONCRETE",
"FROM: " + node,
"TO: " + successorNode,
"NODE STATE: " + node.getState(),
- "NODE STATE (NARROWED): " + nodeStateAfterNarrowing,
- "TRANSFER FN: " + transferFunction,
+ "NODE STATE (NARROWED): "
+ + (nodeStateAfterNarrowing.equals(node.getState())
+ ? "<unchanged>"
+ : nodeStateAfterNarrowing),
+ "TRANSFER FN: " + transferFunction + StringUtils.joinLines(transferFunctionDependencies),
"TRANSFER STATE: " + transferState,
"SUCCESSOR STATE: " + oldSuccessorState,
- "SUCCESSOR STATE (NEW): " + successorNode.getState());
+ "SUCCESSOR STATE (NEW): "
+ + (newSuccessorState.equals(oldSuccessorState) ? "<unchanged>" : newSuccessorState));
}
return true;
}