Narrow unknown state using static type in value propagation
Fixes: b/296030319
Bug: b/330674939
Change-Id: I6eef571e1acb1cb28fb6338c50a0a037c6876294
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 aa7f88a..b3ab15a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -85,6 +85,10 @@
return DynamicType.create(appView, toTypeElement(appView, nullability));
}
+ public TypeElement toNonNullTypeElement(AppView<?> appView) {
+ return toTypeElement(appView, Nullability.definitelyNotNull());
+ }
+
public TypeElement toTypeElement(AppView<?> appView) {
return toTypeElement(appView, Nullability.maybeNull());
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index 8cd6e37..af58cdc 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -55,6 +55,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
+// TODO(b/330674939): Remove legacy field optimizations.
public class FieldAssignmentTracker {
private final AbstractValueFactory abstractValueFactory;
@@ -240,8 +241,9 @@
assert fieldState.isClassState();
ConcreteClassTypeValueState classFieldState = fieldState.asClassState();
+ DexType inStaticType = null;
return classFieldState.mutableJoin(
- appView, abstractValue, value.getDynamicType(appView), field);
+ appView, abstractValue, value.getDynamicType(appView), inStaticType, field);
});
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicType.java b/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicType.java
index e31d2db..971a56e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicType.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/DynamicType.java
@@ -155,25 +155,44 @@
return false;
}
- public DynamicType join(AppView<AppInfoWithLiveness> appView, DynamicType dynamicType) {
- if (isBottom()) {
- return dynamicType;
- }
- if (dynamicType.isBottom() || equals(dynamicType)) {
+ public final DynamicType join(AppView<AppInfoWithLiveness> appView, DynamicType dynamicType) {
+ return join(appView, dynamicType, null, null);
+ }
+
+ public DynamicType join(
+ AppView<AppInfoWithLiveness> appView,
+ DynamicType inDynamicType,
+ DexType inStaticType,
+ DexType outStaticType) {
+ if (equals(inDynamicType)) {
return this;
}
- if (isUnknown() || dynamicType.isUnknown()) {
+ if (isBottom()) {
+ // Account for the fact that the in-static-type may be more precise than the static type of
+ // the current dynamic type.
+ if (inDynamicType.isNotNullType() && inStaticType != null) {
+ return create(appView, inStaticType.toNonNullTypeElement(appView));
+ }
+ return inDynamicType;
+ }
+ if (inDynamicType.isBottom()) {
+ return this;
+ }
+ if (isUnknown() || inDynamicType.isUnknown()) {
return unknown();
}
- if (isNotNullType() || dynamicType.isNotNullType()) {
- if (getNullability().isNullable() || dynamicType.getNullability().isNullable()) {
- return unknown();
+ if (isNotNullType()) {
+ return inDynamicType.getNullability().isNullable() ? unknown() : this;
+ }
+ if (inDynamicType.isNotNullType()) {
+ if (inStaticType == null || inStaticType.isIdenticalTo(outStaticType)) {
+ return getNullability().isNullable() ? unknown() : inDynamicType;
}
- return definitelyNotNull();
+ inDynamicType = create(appView, inStaticType.toNonNullTypeElement(appView));
}
assert isDynamicTypeWithUpperBound();
- assert dynamicType.isDynamicTypeWithUpperBound();
- return asDynamicTypeWithUpperBound().join(appView, dynamicType.asDynamicTypeWithUpperBound());
+ assert inDynamicType.isDynamicTypeWithUpperBound();
+ return asDynamicTypeWithUpperBound().join(appView, inDynamicType.asDynamicTypeWithUpperBound());
}
public abstract DynamicType rewrittenWithLens(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
index 62573c9..65487d8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
@@ -968,6 +968,13 @@
ordinalToObjectState.put(ordinal, enumState);
if (isEnumWithSubtypes) {
DynamicType dynamicType = field.getOptimizationInfo().getDynamicType();
+ // If the dynamic type is a NotNull dynamic type, then de-canonicalize the dynamic
+ // type. If the static type is an effectively final class then this yields an
+ // exact dynamic type.
+ if (dynamicType.isNotNullType()) {
+ dynamicType =
+ DynamicType.create(appView, field.getType().toNonNullTypeElement(appView));
+ }
if (dynamicType.isExactClassType()) {
valueTypes.put(ordinal, dynamicType.getExactClassType().getClassType());
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index bdb5ede..c2b8988 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -756,7 +756,7 @@
private void computeAbstractFunction(IRCode code, OptimizationFeedback feedback) {
if (ComposeUtils.isUpdateChangedFlags(code, appView.dexItemFactory())) {
- MethodParameter methodParameter = new MethodParameter(code.context().getReference(), 0);
+ MethodParameter methodParameter = new MethodParameter(code.context(), 0);
UpdateChangedFlagsAbstractFunction updateChangedFlagsAbstractFunction =
new UpdateChangedFlagsAbstractFunction(methodParameter);
feedback.setAbstractFunction(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
index 93522cc..4e4d506 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
@@ -97,10 +97,11 @@
}
private MutableFieldOptimizationInfo setAbstractValue(AbstractValue abstractValue) {
- assert getAbstractValue().isUnknown()
- || abstractValue.isNonTrivial()
- || (getAbstractValue().isNullOrAbstractValue()
- && getAbstractValue().asNullOrAbstractValue().getNonNullValue().isSingleFieldValue());
+ // TODO(b/330674939): Reenable assert after removing legacy field optimizations.
+ /*assert getAbstractValue().isUnknown()
+ || abstractValue.isNonTrivial()
+ || (getAbstractValue().isNullOrAbstractValue()
+ && getAbstractValue().asNullOrAbstractValue().getNonNullValue().isSingleFieldValue());*/
this.abstractValue = abstractValue;
return this;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
index 7ee9fb5..4f374e6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
@@ -159,17 +159,26 @@
// TODO(b/296030319): Allow lookups in the FieldStateCollection using DexField keys to avoid the
// need for definitionFor here.
- private boolean isFieldValueAlreadyUnknown(DexField field) {
- return isFieldValueAlreadyUnknown(appView.definitionFor(field).asProgramField());
+ private boolean isFieldValueAlreadyUnknown(DexType staticType, DexField field) {
+ return isFieldValueAlreadyUnknown(staticType, appView.definitionFor(field).asProgramField());
}
- private boolean isFieldValueAlreadyUnknown(ProgramField field) {
- return fieldStates.get(field).isUnknown();
+ private boolean isFieldValueAlreadyUnknown(DexType staticType, ProgramField field) {
+ // Only allow early graph pruning when the two nodes have the same type. If the given field is
+ // unknown, but flows to a field or method parameter with a less precise type, we still want
+ // this type propagation to happen.
+ return fieldStates.get(field).isUnknown() && field.getType().isIdenticalTo(staticType);
}
protected boolean isMethodParameterAlreadyUnknown(
- MethodParameter methodParameter, ProgramMethod method) {
+ DexType staticType, MethodParameter methodParameter, ProgramMethod method) {
assert methodParameter.getMethod().isIdenticalTo(method.getReference());
+ if (methodParameter.getType().isNotIdenticalTo(staticType)) {
+ // Only allow early graph pruning when the two nodes have the same type. If the given method
+ // parameter is unknown, but flows to a field or method parameter with a less precise type,
+ // we still want this type propagation to happen.
+ return false;
+ }
MethodState methodState =
methodStates.get(
method.getDefinition().belongsToDirectPool() || isMonomorphicVirtualMethod(method)
@@ -240,10 +249,12 @@
() -> computeFieldState(fieldPut, field, abstractValueSupplier, context, timing),
timing,
(existingFieldState, fieldStateToAdd) -> {
+ DexType inStaticType = null;
NonEmptyValueState newFieldState =
existingFieldState.mutableJoin(
appView,
fieldStateToAdd,
+ inStaticType,
field.getType(),
StateCloner.getCloner(),
Action.empty());
@@ -306,12 +317,12 @@
// If the value is an argument of the enclosing method or defined by a field-get, then clearly we
// have no information about its abstract value (yet). Instead of treating this as having an
// unknown runtime value, we instead record a flow constraint.
- private InFlow computeInFlow(Value value, ProgramMethod context) {
+ private InFlow computeInFlow(DexType staticType, Value value, ProgramMethod context) {
Value valueRoot = value.getAliasedValue(aliasedValueConfiguration);
if (valueRoot.isArgument()) {
MethodParameter inParameter =
methodParameterFactory.create(context, valueRoot.getDefinition().asArgument().getIndex());
- return castBaseInFlow(widenBaseInFlow(inParameter, context), value);
+ return castBaseInFlow(widenBaseInFlow(staticType, inParameter, context), value);
} else if (valueRoot.isDefinedByInstructionSatisfying(Instruction::isFieldGet)) {
FieldGet fieldGet = valueRoot.getDefinition().asFieldGet();
ProgramField field = fieldGet.resolveField(appView, context).getProgramField();
@@ -320,13 +331,15 @@
}
if (fieldGet.isInstanceGet()) {
Value receiverValue = fieldGet.asInstanceGet().object();
- BaseInFlow receiverInFlow = asBaseInFlowOrNull(computeInFlow(receiverValue, context));
+ BaseInFlow receiverInFlow =
+ asBaseInFlowOrNull(computeInFlow(staticType, receiverValue, context));
if (receiverInFlow != null
- && receiverInFlow.equals(widenBaseInFlow(receiverInFlow, context))) {
+ && receiverInFlow.equals(widenBaseInFlow(staticType, receiverInFlow, context))) {
return new InstanceFieldReadAbstractFunction(receiverInFlow, field.getReference());
}
}
- return castBaseInFlow(widenBaseInFlow(fieldValueFactory.create(field), context), value);
+ return castBaseInFlow(
+ widenBaseInFlow(staticType, fieldValueFactory.create(field), context), value);
}
return null;
}
@@ -344,14 +357,14 @@
return new CastAbstractFunction(inFlow.asBaseInFlow(), checkCast.getType());
}
- private InFlow widenBaseInFlow(BaseInFlow inFlow, ProgramMethod context) {
+ private InFlow widenBaseInFlow(DexType staticType, BaseInFlow inFlow, ProgramMethod context) {
if (inFlow.isFieldValue()) {
- if (isFieldValueAlreadyUnknown(inFlow.asFieldValue().getField())) {
+ if (isFieldValueAlreadyUnknown(staticType, inFlow.asFieldValue().getField())) {
return AbstractFunction.unknown();
}
} else {
assert inFlow.isMethodParameter();
- if (isMethodParameterAlreadyUnknown(inFlow.asMethodParameter(), context)) {
+ if (isMethodParameterAlreadyUnknown(staticType, inFlow.asMethodParameter(), context)) {
return AbstractFunction.unknown();
}
}
@@ -360,7 +373,7 @@
private NonEmptyValueState computeInFlowState(
DexType staticType, Value value, ProgramMethod context) {
- InFlow inFlow = computeInFlow(value, context);
+ InFlow inFlow = computeInFlow(staticType, value, context);
if (inFlow == null) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index 0aca617..be9d7c5 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.ir.analysis.type.DynamicType;
+import com.android.tools.r8.ir.analysis.type.DynamicTypeWithUpperBound;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -154,6 +155,16 @@
}
private void setDynamicType(ProgramField field, DynamicType dynamicType) {
+ if (dynamicType.hasDynamicUpperBoundType()) {
+ DynamicTypeWithUpperBound dynamicTypeWithUpperBound =
+ dynamicType.asDynamicTypeWithUpperBound();
+ if (!dynamicTypeWithUpperBound.strictlyLessThan(
+ field.getType().toTypeElement(appView), appView)) {
+ // TODO(b/296030319): Try to guarantee that the computed dynamic type is strictly more
+ // precise than the static type.
+ return;
+ }
+ }
getSimpleFeedback().markFieldHasDynamicType(field, dynamicType);
}
@@ -298,14 +309,16 @@
continue;
}
DynamicType dynamicType = parameterState.asClassState().getDynamicType();
- DexType staticType = method.getArgumentType(argumentIndex);
- if (shouldWidenDynamicTypeToUnknown(dynamicType, staticType)) {
+ DexType outStaticType = method.getArgumentType(argumentIndex);
+ if (shouldWidenDynamicTypeToUnknown(dynamicType, outStaticType)) {
+ DexType inStaticType = null;
methodState.setParameterState(
argumentIndex,
parameterState.mutableJoin(
appView,
new ConcreteClassTypeValueState(AbstractValue.bottom(), DynamicType.unknown()),
- staticType,
+ inStaticType,
+ outStaticType,
StateCloner.getIdentity()));
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
index 5b5b80c..3f9880b 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -671,8 +671,10 @@
KeepFieldInfo keepInfo = appView.getKeepInfo(field);
- // We don't have dynamic type information for fields that are kept.
- assert !keepInfo.isPinned(options);
+ // We don't have dynamic type information for fields that are kept, unless the static type of
+ // the field is guaranteed to be null.
+ assert !keepInfo.isPinned(options)
+ || (field.getType().isAlwaysNull(appView) && dynamicType.isNullType());
if (!keepInfo.isFieldTypeStrengtheningAllowed(options)) {
return staticType;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java
index 98e6bfc..dafacba 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomArrayTypeValueState.java
@@ -23,19 +23,20 @@
@Override
public ValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction) {
- if (state.isBottom()) {
+ if (inState.isBottom()) {
return this;
}
- if (state.isUnknown()) {
- return state;
+ if (inState.isUnknown()) {
+ return inState;
}
- assert state.isConcrete();
- assert state.asConcrete().isReferenceState();
- ConcreteReferenceTypeValueState concreteState = state.asConcrete().asReferenceState();
+ assert inState.isConcrete();
+ assert inState.asConcrete().isReferenceState();
+ ConcreteReferenceTypeValueState concreteState = inState.asConcrete().asReferenceState();
if (concreteState.isArrayState()) {
return cloner.mutableCopy(concreteState);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java
index f8745d8..b44361c 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomClassTypeValueState.java
@@ -25,29 +25,43 @@
@Override
public ValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction) {
- if (state.isBottom()) {
+ if (inState.isBottom()) {
return this;
}
- if (state.isUnknown()) {
- return state;
+ if (inState.isUnknown()) {
+ return inState;
}
- assert state.isConcrete();
- assert state.asConcrete().isReferenceState();
- ConcreteReferenceTypeValueState concreteState = state.asConcrete().asReferenceState();
- AbstractValue abstractValue = concreteState.getAbstractValue(appView);
- DynamicType dynamicType = concreteState.getDynamicType();
- DynamicType widenedDynamicType =
- WideningUtils.widenDynamicNonReceiverType(appView, dynamicType, staticType);
- if (concreteState.isClassState() && !widenedDynamicType.isUnknown()) {
+ assert inState.isConcrete();
+ assert inState.asConcrete().isReferenceState();
+ ConcreteReferenceTypeValueState concreteState = inState.asConcrete().asReferenceState();
+ DynamicType joinedDynamicType =
+ joinDynamicType(appView, concreteState.getDynamicType(), inStaticType, outStaticType);
+ if (concreteState.isClassState() && concreteState.getDynamicType().equals(joinedDynamicType)) {
return cloner.mutableCopy(concreteState);
}
- return abstractValue.isUnknown() && widenedDynamicType.isUnknown()
- ? unknown()
- : new ConcreteClassTypeValueState(
- abstractValue, widenedDynamicType, concreteState.copyInFlow());
+ AbstractValue abstractValue = concreteState.getAbstractValue(appView);
+ return ConcreteClassTypeValueState.create(
+ abstractValue, joinedDynamicType, concreteState.copyInFlow());
+ }
+
+ private DynamicType joinDynamicType(
+ AppView<AppInfoWithLiveness> appView,
+ DynamicType inDynamicType,
+ DexType inStaticType,
+ DexType outStaticType) {
+ DynamicType oldDynamicType = DynamicType.bottom();
+ DynamicType joinedDynamicType =
+ oldDynamicType.join(appView, inDynamicType, inStaticType, outStaticType);
+ if (outStaticType != null) {
+ return WideningUtils.widenDynamicNonReceiverType(appView, joinedDynamicType, outStaticType);
+ } else {
+ assert !joinedDynamicType.isUnknown();
+ return joinedDynamicType;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java
index 567a559..67c0736 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomPrimitiveTypeValueState.java
@@ -22,18 +22,19 @@
@Override
public ValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction) {
- if (state.isBottom()) {
- assert state == bottomPrimitiveTypeState();
+ if (inState.isBottom()) {
+ assert inState == bottomPrimitiveTypeState();
return this;
}
- if (state.isUnknown()) {
- return state;
+ if (inState.isUnknown()) {
+ return inState;
}
- assert state.isPrimitiveState();
- return cloner.mutableCopy(state);
+ assert inState.isPrimitiveState();
+ return cloner.mutableCopy(inState);
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java
index b8eb62e..9a9bb39 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/BottomReceiverValueState.java
@@ -23,19 +23,20 @@
@Override
public ValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction) {
- if (state.isBottom()) {
+ if (inState.isBottom()) {
return this;
}
- if (state.isUnknown()) {
- return state;
+ if (inState.isUnknown()) {
+ return inState;
}
- assert state.isConcrete();
- assert state.asConcrete().isReferenceState();
- ConcreteReferenceTypeValueState concreteState = state.asConcrete().asReferenceState();
+ assert inState.isConcrete();
+ assert inState.asConcrete().isReferenceState();
+ ConcreteReferenceTypeValueState concreteState = inState.asConcrete().asReferenceState();
if (concreteState.isReceiverState()) {
return cloner.mutableCopy(concreteState);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java
index 722aef5..6e17619 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteArrayTypeValueState.java
@@ -109,15 +109,16 @@
@Override
public NonEmptyValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ConcreteReferenceTypeValueState state,
- DexType staticType,
+ ConcreteReferenceTypeValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
Action onChangedAction) {
- assert staticType.isArrayType();
- boolean nullabilityChanged = mutableJoinNullability(state.getNullability());
+ assert outStaticType.isArrayType();
+ boolean nullabilityChanged = mutableJoinNullability(inState.getNullability());
if (isEffectivelyUnknown()) {
return unknown();
}
- boolean inFlowChanged = mutableJoinInFlow(state);
+ boolean inFlowChanged = mutableJoinInFlow(inState);
if (widenInFlow(appView)) {
return unknown();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
index 320c89c..8542763 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteClassTypeValueState.java
@@ -40,9 +40,14 @@
}
public static NonEmptyValueState create(AbstractValue abstractValue, DynamicType dynamicType) {
+ return create(abstractValue, dynamicType, Collections.emptySet());
+ }
+
+ public static NonEmptyValueState create(
+ AbstractValue abstractValue, DynamicType dynamicType, Set<InFlow> inFlow) {
return abstractValue.isUnknown() && dynamicType.isUnknown()
? ValueState.unknown()
- : new ConcreteClassTypeValueState(abstractValue, dynamicType);
+ : new ConcreteClassTypeValueState(abstractValue, dynamicType, inFlow);
}
@Override
@@ -61,7 +66,9 @@
@Override
public AbstractValue getAbstractValue(AppView<AppInfoWithLiveness> appView) {
if (getNullability().isDefinitelyNull()) {
- assert abstractValue.isNull() || abstractValue.isUnknown();
+ assert abstractValue.isNull()
+ || abstractValue.isNullOrAbstractValue()
+ || abstractValue.isUnknown();
return appView.abstractValueFactory().createUncheckedNullValue();
}
return abstractValue;
@@ -115,11 +122,12 @@
public NonEmptyValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
AbstractValue abstractValue,
- DynamicType dynamicType,
+ DynamicType inDynamicType,
+ DexType inStaticType,
ProgramField field) {
assert field.getType().isClassType();
mutableJoinAbstractValue(appView, abstractValue, field.getType());
- mutableJoinDynamicType(appView, dynamicType, field.getType());
+ mutableJoinDynamicType(appView, inDynamicType, inStaticType, field.getType());
if (isEffectivelyUnknown()) {
return unknown();
}
@@ -129,18 +137,19 @@
@Override
public NonEmptyValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ConcreteReferenceTypeValueState state,
- DexType staticType,
+ ConcreteReferenceTypeValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
Action onChangedAction) {
- assert staticType.isClassType();
+ assert outStaticType.isClassType();
boolean abstractValueChanged =
- mutableJoinAbstractValue(appView, state.getAbstractValue(appView), staticType);
+ mutableJoinAbstractValue(appView, inState.getAbstractValue(appView), outStaticType);
boolean dynamicTypeChanged =
- mutableJoinDynamicType(appView, state.getDynamicType(), staticType);
+ mutableJoinDynamicType(appView, inState.getDynamicType(), inStaticType, outStaticType);
if (isEffectivelyUnknown()) {
return unknown();
}
- boolean inFlowChanged = mutableJoinInFlow(state);
+ boolean inFlowChanged = mutableJoinInFlow(inState);
if (widenInFlow(appView)) {
return unknown();
}
@@ -161,11 +170,15 @@
}
private boolean mutableJoinDynamicType(
- AppView<AppInfoWithLiveness> appView, DynamicType otherDynamicType, DexType staticType) {
+ AppView<AppInfoWithLiveness> appView,
+ DynamicType inDynamicType,
+ DexType inStaticType,
+ DexType outStaticType) {
DynamicType oldDynamicType = dynamicType;
- DynamicType joinedDynamicType = dynamicType.join(appView, otherDynamicType);
+ DynamicType joinedDynamicType =
+ dynamicType.join(appView, inDynamicType, inStaticType, outStaticType);
DynamicType widenedDynamicType =
- WideningUtils.widenDynamicNonReceiverType(appView, joinedDynamicType, staticType);
+ WideningUtils.widenDynamicNonReceiverType(appView, joinedDynamicType, outStaticType);
dynamicType = widenedDynamicType;
return !dynamicType.equals(oldDynamicType);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
index b2b1862..e150610 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteMonomorphicMethodState.java
@@ -88,19 +88,24 @@
assert size() == methodSignature.getArity() + 1;
ValueState parameterState = parameterStates.get(0);
ValueState otherParameterState = methodState.parameterStates.get(0);
- DexType parameterType = null;
+ DexType inStaticType = null;
+ DexType outStaticType = null;
parameterStates.set(
- 0, parameterState.mutableJoin(appView, otherParameterState, parameterType, cloner));
+ 0,
+ parameterState.mutableJoin(
+ appView, otherParameterState, inStaticType, outStaticType, cloner));
argumentIndex++;
}
for (int parameterIndex = 0; argumentIndex < size(); argumentIndex++, parameterIndex++) {
ValueState parameterState = parameterStates.get(argumentIndex);
ValueState otherParameterState = methodState.parameterStates.get(argumentIndex);
- DexType parameterType = methodSignature.getParameter(parameterIndex);
+ DexType inStaticType = null;
+ DexType outStaticType = methodSignature.getParameter(parameterIndex);
parameterStates.set(
argumentIndex,
- parameterState.mutableJoin(appView, otherParameterState, parameterType, cloner));
+ parameterState.mutableJoin(
+ appView, otherParameterState, inStaticType, outStaticType, cloner));
assert !parameterStates.get(argumentIndex).isConcrete()
|| !parameterStates.get(argumentIndex).asConcrete().isReceiverState();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
index 8a1a137..894ad96 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReceiverValueState.java
@@ -99,18 +99,19 @@
@Override
public NonEmptyValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ConcreteReferenceTypeValueState state,
- DexType staticType,
+ ConcreteReferenceTypeValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
Action onChangedAction) {
// TODO(b/190154391): Always take in the static type as an argument, and unset the dynamic type
// if it equals the static type.
- assert staticType == null || staticType.isClassType();
+ assert outStaticType == null || outStaticType.isClassType();
boolean dynamicTypeChanged =
- mutableJoinDynamicType(appView, state.getDynamicType(), staticType);
+ mutableJoinDynamicType(appView, inState.getDynamicType(), inStaticType, outStaticType);
if (isEffectivelyUnknown()) {
return unknown();
}
- boolean inFlowChanged = mutableJoinInFlow(state);
+ boolean inFlowChanged = mutableJoinInFlow(inState);
if (widenInFlow(appView)) {
return unknown();
}
@@ -121,12 +122,16 @@
}
private boolean mutableJoinDynamicType(
- AppView<AppInfoWithLiveness> appView, DynamicType otherDynamicType, DexType staticType) {
+ AppView<AppInfoWithLiveness> appView,
+ DynamicType inDynamicType,
+ DexType inStaticType,
+ DexType outStaticType) {
DynamicType oldDynamicType = dynamicType;
- DynamicType joinedDynamicType = dynamicType.join(appView, otherDynamicType);
- if (staticType != null) {
+ DynamicType joinedDynamicType =
+ dynamicType.join(appView, inDynamicType, inStaticType, outStaticType);
+ if (outStaticType != null) {
DynamicType widenedDynamicType =
- WideningUtils.widenDynamicNonReceiverType(appView, joinedDynamicType, staticType);
+ WideningUtils.widenDynamicNonReceiverType(appView, joinedDynamicType, outStaticType);
assert !widenedDynamicType.isUnknown();
dynamicType = widenedDynamicType;
} else {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReferenceTypeValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReferenceTypeValueState.java
index 951ea07..ff432b9 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReferenceTypeValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteReferenceTypeValueState.java
@@ -41,7 +41,9 @@
if (typeElement.lessThanOrEqual(lowerBound, appView)) {
return DynamicType.create(appView, typeElement, lowerBound);
} else {
- return DynamicType.bottom();
+ return dynamicType.getNullability().isMaybeNull()
+ ? DynamicType.definitelyNull()
+ : DynamicType.bottom();
}
}
return DynamicType.create(appView, typeElement);
@@ -63,7 +65,8 @@
public abstract NonEmptyValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ConcreteReferenceTypeValueState state,
- DexType staticType,
+ ConcreteReferenceTypeValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
Action onChangedAction);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteValueState.java
index e32324a..d6193f6 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ConcreteValueState.java
@@ -104,24 +104,30 @@
@Override
public final NonEmptyValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction) {
- if (state.isBottom()) {
+ if (inState.isBottom()) {
return this;
}
- if (state.isUnknown()) {
+ if (inState.isUnknown()) {
return unknown();
}
- ConcreteValueState concreteState = state.asConcrete();
+ ConcreteValueState concreteState = inState.asConcrete();
if (isReferenceState()) {
assert concreteState.isReferenceState();
return asReferenceState()
- .mutableJoin(appView, concreteState.asReferenceState(), staticType, onChangedAction);
+ .mutableJoin(
+ appView,
+ concreteState.asReferenceState(),
+ inStaticType,
+ outStaticType,
+ onChangedAction);
}
return asPrimitiveState()
- .mutableJoin(appView, concreteState.asPrimitiveState(), staticType, onChangedAction);
+ .mutableJoin(appView, concreteState.asPrimitiveState(), outStaticType, onChangedAction);
}
boolean mutableJoinInFlow(ConcreteValueState state) {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldStateCollection.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldStateCollection.java
index 544c365..cf0dcc5 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldStateCollection.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/FieldStateCollection.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.optimize.argumentpropagation.codescanner;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Action;
@@ -34,13 +35,16 @@
field,
fieldStateSupplier,
timing,
- (existingFieldState, fieldStateToAdd) ->
- existingFieldState.mutableJoin(
- appView,
- fieldStateToAdd,
- field.getType(),
- StateCloner.getCloner(),
- Action.empty()));
+ (existingFieldState, fieldStateToAdd) -> {
+ DexType inStaticType = null;
+ return existingFieldState.mutableJoin(
+ appView,
+ fieldStateToAdd,
+ inStaticType,
+ field.getType(),
+ StateCloner.getCloner(),
+ Action.empty());
+ });
}
/**
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 2fe1a2a..7ebb2d0 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
@@ -4,17 +4,29 @@
package com.android.tools.r8.optimize.argumentpropagation.codescanner;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
import java.util.Objects;
public class MethodParameter implements BaseInFlow {
private final DexMethod method;
private final int index;
+ private final boolean isMethodStatic;
- public MethodParameter(DexMethod method, int index) {
+ public MethodParameter(DexClassAndMethod method, int index) {
+ this(method.getReference(), index, method.getAccessFlags().isStatic());
+ }
+
+ public MethodParameter(DexMethod method, int index, boolean isMethodStatic) {
this.method = method;
this.index = index;
+ this.isMethodStatic = isMethodStatic;
+ }
+
+ public static MethodParameter createStatic(DexMethod method, int index) {
+ return new MethodParameter(method, index, true);
}
public DexMethod getMethod() {
@@ -25,6 +37,10 @@
return index;
}
+ public DexType getType() {
+ return method.getArgumentType(index, isMethodStatic);
+ }
+
@Override
public boolean isMethodParameter() {
return true;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameterFactory.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameterFactory.java
index d1501e6..16267c2 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameterFactory.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/MethodParameterFactory.java
@@ -15,6 +15,6 @@
public MethodParameter create(ProgramMethod method, int argumentIndex) {
return methodParameters.computeIfAbsent(
- new MethodParameter(method.getReference(), argumentIndex), Function.identity());
+ new MethodParameter(method, argumentIndex), Function.identity());
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java
index 6e3601b..843e64d 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/UnknownValueState.java
@@ -39,8 +39,9 @@
@Override
public UnknownValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction) {
return this;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ValueState.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ValueState.java
index 96adb2c..06cb1eb 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ValueState.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/codescanner/ValueState.java
@@ -120,16 +120,18 @@
public final ValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType parameterType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner) {
- return mutableJoin(appView, state, parameterType, cloner, Action.empty());
+ return mutableJoin(appView, inState, inStaticType, outStaticType, cloner, Action.empty());
}
public abstract ValueState mutableJoin(
AppView<AppInfoWithLiveness> appView,
- ValueState state,
- DexType staticType,
+ ValueState inState,
+ DexType inStaticType,
+ DexType outStaticType,
StateCloner cloner,
Action onChangedAction);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/DefaultFieldValueJoiner.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/DefaultFieldValueJoiner.java
index 294eb8e..9274830 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/DefaultFieldValueJoiner.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/DefaultFieldValueJoiner.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.DynamicType;
@@ -229,9 +230,11 @@
node -> {
ProgramField field = node.getField();
if (fieldsWithLiveDefaultValue.remove(field)) {
+ DexType inStaticType = null;
node.addState(
appView,
getDefaultValueState(field),
+ inStaticType,
() -> {
if (node.isUnknown()) {
node.clearPredecessors();
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java
index 00d36e6..061c898 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/propagation/FlowGraphBuilder.java
@@ -203,7 +203,7 @@
}
ValueState fieldState = getFieldState(field, fieldStates);
- if (fieldState.isUnknown()) {
+ if (fieldState.isUnknown() && field.getType().isIdenticalTo(node.getStaticType())) {
// The current node depends on a field for which we don't know anything.
node.clearPredecessors();
node.setStateToUnknown();
@@ -237,19 +237,17 @@
return TraversalContinuation.doContinue();
}
- if (enclosingMethodState.isUnknown()) {
+ assert enclosingMethodState.isMonomorphic() || enclosingMethodState.isUnknown();
+
+ if (enclosingMethodState.isUnknown() && inFlow.getType().isIdenticalTo(node.getStaticType())) {
// The current node depends on a parameter for which we don't know anything.
node.clearPredecessors();
node.setStateToUnknown();
return TraversalContinuation.doBreak();
}
- assert enclosingMethodState.isConcrete();
- assert enclosingMethodState.asConcrete().isMonomorphic();
-
FlowGraphParameterNode predecessor =
- getOrCreateParameterNode(
- enclosingMethod, inFlow.getIndex(), enclosingMethodState.asConcrete().asMonomorphic());
+ getOrCreateParameterNode(enclosingMethod, inFlow.getIndex(), enclosingMethodState);
node.addPredecessor(predecessor, transferFunction);
return TraversalContinuation.doContinue();
}
@@ -260,7 +258,7 @@
}
private FlowGraphParameterNode getOrCreateParameterNode(
- ProgramMethod method, int parameterIndex, ConcreteMonomorphicMethodState methodState) {
+ ProgramMethod method, int parameterIndex, MethodState methodState) {
Int2ReferenceMap<FlowGraphParameterNode> parameterNodesForMethod =
parameterNodes.computeIfAbsent(
method.getReference(), ignoreKey(Int2ReferenceOpenHashMap::new));
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 3547464..5649bbc 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
@@ -30,11 +30,19 @@
private boolean inWorklist = true;
void addState(
- AppView<AppInfoWithLiveness> appView, ConcreteValueState stateToAdd, Action onChangedAction) {
+ AppView<AppInfoWithLiveness> appView,
+ ConcreteValueState inState,
+ DexType inStaticType,
+ Action onChangedAction) {
ValueState oldState = getState();
ValueState newState =
oldState.mutableJoin(
- appView, stateToAdd, getStaticType(), StateCloner.getCloner(), onChangedAction);
+ appView,
+ inState,
+ inStaticType,
+ getStaticType(),
+ StateCloner.getCloner(),
+ onChangedAction);
if (newState != oldState) {
setState(newState);
onChangedAction.execute();
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 eccd2db..12d516b 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,21 +5,19 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.optimize.argumentpropagation.codescanner.ConcreteMonomorphicMethodState;
+import com.android.tools.r8.optimize.argumentpropagation.codescanner.MethodState;
import com.android.tools.r8.optimize.argumentpropagation.codescanner.ValueState;
class FlowGraphParameterNode extends FlowGraphNode {
private final ProgramMethod method;
- private final ConcreteMonomorphicMethodState methodState;
+ private final MethodState methodState;
private final int parameterIndex;
private final DexType parameterType;
FlowGraphParameterNode(
- ProgramMethod method,
- ConcreteMonomorphicMethodState methodState,
- int parameterIndex,
- DexType parameterType) {
+ ProgramMethod method, MethodState methodState, int parameterIndex, DexType parameterType) {
+ assert methodState.isMonomorphic() || methodState.isUnknown();
this.method = method;
this.methodState = methodState;
this.parameterIndex = parameterIndex;
@@ -41,12 +39,18 @@
@Override
ValueState getState() {
- return methodState.getParameterState(parameterIndex);
+ return methodState.isMonomorphic()
+ ? methodState.asMonomorphic().getParameterState(parameterIndex)
+ : ValueState.unknown();
}
@Override
void setState(ValueState parameterState) {
- methodState.setParameterState(parameterIndex, parameterState);
+ if (methodState.isMonomorphic()) {
+ methodState.asMonomorphic().setParameterState(parameterIndex, parameterState);
+ } else {
+ assert parameterState.isUnknown();
+ }
}
@Override
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 2aa21de..0794838 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
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.DynamicType;
@@ -235,9 +236,10 @@
successorNode.setStateToUnknown();
successorNode.addToWorkList(worklist);
} else {
- ConcreteValueState concreteTransferState = transferState.asConcrete();
+ ConcreteValueState inState = transferState.asConcrete();
+ DexType inStaticType = transferFunction.isIdentity() ? node.getStaticType() : null;
successorNode.addState(
- appView, concreteTransferState, () -> successorNode.addToWorkList(worklist));
+ appView, inState, inStaticType, () -> successorNode.addToWorkList(worklist));
}
// 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/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java
index 07a8bc7..1eec104 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsAnalysis.java
@@ -120,8 +120,7 @@
Set<MethodParameter> effectivelyUnusedConstraints =
computeEffectivelyUnusedConstraints(method, argument, argumentValue);
if (effectivelyUnusedConstraints != null && !effectivelyUnusedConstraints.isEmpty()) {
- MethodParameter methodParameter =
- new MethodParameter(method.getReference(), argument.getIndex());
+ MethodParameter methodParameter = new MethodParameter(method, argument.getIndex());
assert !constraints.containsKey(methodParameter);
constraints.put(methodParameter, effectivelyUnusedConstraints);
}
@@ -161,7 +160,7 @@
return null;
}
effectivelyUnusedConstraints.add(
- new MethodParameter(resolvedMethod.getReference(), dependentArgumentIndex));
+ new MethodParameter(resolvedMethod, dependentArgumentIndex));
} else {
return null;
}
@@ -222,7 +221,7 @@
for (int argumentIndex = 0;
argumentIndex < method.getDefinition().getNumberOfArguments();
argumentIndex++) {
- constraints.remove(new MethodParameter(method.getReference(), argumentIndex));
+ constraints.remove(new MethodParameter(method, argumentIndex));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java
index 964fca7..1f795ad 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/unusedarguments/EffectivelyUnusedArgumentsGraph.java
@@ -116,7 +116,7 @@
assert node.getSuccessors().isEmpty();
assert node.getPredecessors().isEmpty();
MethodParameter methodParameter =
- new MethodParameter(node.getMethod().getReference(), node.getArgumentIndex());
+ new MethodParameter(node.getMethod(), node.getArgumentIndex());
EffectivelyUnusedArgumentsGraphNode removed = nodes.remove(methodParameter);
assert removed == node;
}
@@ -168,7 +168,7 @@
boolean verifyContains(EffectivelyUnusedArgumentsGraphNode node) {
MethodParameter methodParameter =
- new MethodParameter(node.getMethod().getReference(), node.getArgumentIndex());
+ new MethodParameter(node.getMethod(), node.getArgumentIndex());
return nodes.containsKey(methodParameter);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java b/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java
index 5d0b693..174e8ba 100644
--- a/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java
+++ b/src/main/java/com/android/tools/r8/optimize/compose/ArgumentPropagatorCodeScannerForComposableFunctions.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.optimize.compose;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.AbstractValueSupplier;
import com.android.tools.r8.ir.code.InvokeMethod;
@@ -38,7 +39,7 @@
@Override
protected boolean isMethodParameterAlreadyUnknown(
- MethodParameter methodParameter, ProgramMethod method) {
+ DexType staticType, MethodParameter methodParameter, ProgramMethod method) {
// We haven't defined the virtual root mapping, so we can't tell.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java b/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java
index 846dcbe..940a341 100644
--- a/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/optimize/compose/ComposeMethodProcessor.java
@@ -186,7 +186,9 @@
.addTemporaryFieldState(
appView,
field,
- () -> new ConcretePrimitiveTypeValueState(new MethodParameter(method, parameterIndex)),
+ () ->
+ new ConcretePrimitiveTypeValueState(
+ MethodParameter.createStatic(method, parameterIndex)),
Timing.empty());
}
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index 0c816c4..f4c915f 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -128,7 +128,7 @@
.withOptionConsumer(opts -> opts.enableClassInlining = false)
.withBuilderTransformation(
b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 5, "lambdadesugaring"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 4, "lambdadesugaring"))
.run(Paths.get(ToolHelper.THIRD_PARTY_DIR, "examplesAndroidOLegacy"));
test("lambdadesugaring", "lambdadesugaring", "LambdaDesugaring")
@@ -167,7 +167,7 @@
.withOptionConsumer(opts -> opts.enableClassInlining = false)
.withBuilderTransformation(
b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 5, "lambdadesugaring"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 4, "lambdadesugaring"))
.run(Paths.get(ToolHelper.THIRD_PARTY_DIR, "examplesAndroidOLegacy"));
test("lambdadesugaring", "lambdadesugaring", "LambdaDesugaring")
@@ -205,7 +205,7 @@
.withDexCheck(
inspector ->
checkLambdaCount(
- inspector, enableProguardCompatibilityMode ? 4 : 5, "lambdadesugaringnplus"))
+ inspector, enableProguardCompatibilityMode ? 3 : 4, "lambdadesugaringnplus"))
.run();
test("lambdadesugaringnplus", "lambdadesugaringnplus", "LambdasWithStaticAndDefaultMethods")
@@ -217,10 +217,7 @@
b ->
b.addProguardConfiguration(
getProguardOptionsNPlus(enableProguardCompatibilityMode), Origin.unknown()))
- .withDexCheck(
- inspector ->
- checkLambdaCount(
- inspector, enableProguardCompatibilityMode ? 1 : 2, "lambdadesugaringnplus"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 0, "lambdadesugaringnplus"))
.run();
}
@@ -250,7 +247,7 @@
b ->
b.addProguardConfiguration(
getProguardOptionsNPlus(enableProguardCompatibilityMode), Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 5, "lambdadesugaringnplus"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 4, "lambdadesugaringnplus"))
.run();
test("lambdadesugaringnplus", "lambdadesugaringnplus", "LambdasWithStaticAndDefaultMethods")
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/EquivalentConstructorsWithoutClassIdAfterUnusedArgumentRemovalMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/EquivalentConstructorsWithoutClassIdAfterUnusedArgumentRemovalMergingTest.java
index b1c5187..51c434b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/EquivalentConstructorsWithoutClassIdAfterUnusedArgumentRemovalMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/EquivalentConstructorsWithoutClassIdAfterUnusedArgumentRemovalMergingTest.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverPropagateValue;
import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -46,6 +47,7 @@
inspector ->
inspector.assertIsCompleteMergeGroup(A.class, B.class).assertNoOtherClassesMerged())
.enableInliningAnnotations()
+ .enableMemberValuePropagationAnnotations()
.enableNeverClassInliningAnnotations()
.enableNoHorizontalClassMergingAnnotations()
.setMinApi(parameters)
@@ -72,7 +74,7 @@
@NeverClassInline
static class A {
- private final C c;
+ @NeverPropagateValue private final C c;
A(Object unused, C c) {
this.c = c;
@@ -87,7 +89,7 @@
@NeverClassInline
static class B {
- private final D d;
+ @NeverPropagateValue private final D d;
B(Object unused, D d) {
this.d = d;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index 780e944..12e89e5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -321,7 +321,7 @@
// These constants describe the expected number of invoke instructions calling a possibly
// inlined method.
int ALWAYS_INLINABLE = 0;
- int INLINABLE_WHEN_DISABLED = allowAccessModification ? 1 : 0;
+ int INLINABLE_WHEN_DISABLED = allowAccessModification && parameters.isDexRuntime() ? 1 : 0;
int NEVER_INLINABLE = 1;
ClassSubject clazz = inspector.clazz(nullabilityClass);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java
index 7e61ae9..9ec6561 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java
@@ -57,8 +57,8 @@
});
// TODO(b/126323172) Add test here to check the same with desugared lambdas.
- assertEquals(0, counts.run);
- assertEquals(2, counts.println);
+ assertEquals(1, counts.run);
+ assertEquals(1, counts.println);
}
private static long countInvokesWithName(MethodSubject methodSubject, String name) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java
index eb3ffad..198ffe2 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinClassInlinerTest.java
@@ -14,6 +14,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.cf.code.CfInstruction;
@@ -205,6 +206,16 @@
"kotlin.sequences.TransformingSequence"),
Reference.classFromTypeName(
"kotlin.sequences.GeneratorSequence"))
+ .applyIf(
+ kotlinParameters
+ .getCompiler()
+ .getCompilerVersion()
+ .isEqualTo(KotlinCompilerVersion.KOTLINC_1_9_21),
+ i ->
+ i.assertIsCompleteMergeGroup(
+ SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 0),
+ SyntheticItemsTestUtils.syntheticLambdaClass(
+ mainKt, 1)))
.assertNoOtherClassesMerged();
} else {
assert kotlinParameters.getLambdaGeneration().isInvokeDynamic()
@@ -228,7 +239,7 @@
assertThat(
inspector.clazz(
"class_inliner_lambda_k_style.MainKt$testKotlinSequencesStateful$1"),
- isPresent());
+ isAbsent());
assertThat(
inspector.clazz("class_inliner_lambda_k_style.MainKt$testBigExtraMethod$1"),
isPresent());
@@ -258,7 +269,7 @@
isAbsent());
assertThat(
inspector.clazz("class_inliner_lambda_k_style.MainKt$testBigExtraMethod$1"),
- isAbsentIf(testParameters.isDexRuntime()));
+ isPresent());
}
});
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingCapturesKotlinStyleTest.java b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingCapturesKotlinStyleTest.java
index 75c0867..fb66676 100644
--- a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingCapturesKotlinStyleTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingCapturesKotlinStyleTest.java
@@ -13,8 +13,6 @@
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.ClassReference;
-import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -76,7 +74,8 @@
testForR8(parameters.getBackend())
.addProgramFiles(getProgramFiles())
.addKeepMainRule(getMainClassName())
- .addHorizontallyMergedClassesInspector(inspector -> inspect(inspector, lambdasInInput))
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
.allowAccessModification(allowAccessModification)
.allowDiagnosticWarningMessages()
.setMinApi(parameters)
@@ -88,43 +87,6 @@
.assertSuccessWithOutput(getExpectedOutput());
}
- private void inspect(
- HorizontallyMergedClassesInspector inspector, KotlinLambdasInInput lambdasInInput) {
- if (parameters.isCfRuntime()) {
- inspector.assertNoClassesMerged();
- return;
- }
-
- if (kotlinParameters.getLambdaGeneration().isClass()) {
- inspector
- .assertIsCompleteMergeGroup(
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$1"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$2"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$3"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$4"))
- .assertIsCompleteMergeGroup(
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$5"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$6"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$7"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(getTestName(), "MainKt$test2$8"))
- .assertNoOtherClassesMerged();
- } else {
- ClassReference mainKt = Reference.classFromTypeName(getMainClassName());
- inspector
- .assertIsCompleteMergeGroup(
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 0),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 2),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 3),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 4))
- .assertIsCompleteMergeGroup(
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 5),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 6),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 7),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 8))
- .assertNoOtherClassesMerged();
- }
- }
-
private void inspect(CodeInspector inspector, KotlinLambdasInInput lambdasInInput) {
List<ClassReference> presentKStyleLambdas = new ArrayList<>();
for (ClassReference classReference : lambdasInInput.getKStyleLambdas()) {
@@ -132,11 +94,7 @@
presentKStyleLambdas.add(classReference);
}
}
- assertEquals(
- parameters.isCfRuntime() || kotlinParameters.getLambdaGeneration().isInvokeDynamic()
- ? 0
- : 5,
- presentKStyleLambdas.size());
+ assertEquals(0, presentKStyleLambdas.size());
}
private String getExpectedOutput() {
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingKeepAttributesKotlinStyleTest.java b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingKeepAttributesKotlinStyleTest.java
index c6c7823..2fa8198 100644
--- a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingKeepAttributesKotlinStyleTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingKeepAttributesKotlinStyleTest.java
@@ -12,6 +12,7 @@
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
@@ -108,6 +109,12 @@
inspector
.assertIsCompleteMergeGroup(
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testFirst$1"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testFirst$2"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testFirst$3"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$4"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$5"),
@@ -120,6 +127,12 @@
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$9"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testSecond$1"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testSecond$2"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testSecond$3"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testSecond$4"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testSecond$5"),
@@ -130,20 +143,7 @@
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testSecond$8"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$9"))
- .assertIsCompleteMergeGroup(
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testFirst$1"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testFirst$2"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testFirst$3"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$1"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$2"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$3"),
+ getTestName(), "MainKt$testSecond$9"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testThird$1"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
@@ -167,17 +167,6 @@
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$3"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$1"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$2"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$3"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testThird$1"),
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testThird$2"))
- .assertIsCompleteMergeGroup(
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$4"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$5"),
@@ -190,6 +179,12 @@
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testFirst$9"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testSecond$1"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testSecond$2"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testSecond$3"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testSecond$4"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testSecond$5"),
@@ -200,12 +195,16 @@
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testSecond$8"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testSecond$9"))
+ getTestName(), "MainKt$testSecond$9"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testThird$1"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testThird$2"))
.assertNoOtherClassesMerged();
} else {
ClassReference mainKt = Reference.classFromTypeName(getMainClassName());
- inspector
- .assertIsCompleteMergeGroup(
+ List<ClassReference> mergeGroup =
+ ImmutableList.of(
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 9),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 10),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 11),
@@ -217,8 +216,9 @@
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 20),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 21),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 22),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 23))
- .assertIsCompleteMergeGroup(
+ SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 23));
+ List<ClassReference> otherMergeGroup =
+ ImmutableList.of(
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 0),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 1),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 2),
@@ -230,7 +230,21 @@
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 8),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 15),
SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 16),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 17))
+ SyntheticItemsTestUtils.syntheticLambdaClass(mainKt, 17));
+ inspector
+ .applyIf(
+ kotlinc.is(KotlinCompilerVersion.KOTLINC_1_9_21)
+ && parameters.isDexRuntime()
+ && lambdaGeneration.isInvokeDynamic(),
+ i ->
+ i.assertIsCompleteMergeGroup(
+ ImmutableList.<ClassReference>builder()
+ .addAll(mergeGroup)
+ .addAll(otherMergeGroup)
+ .build()),
+ i ->
+ i.assertIsCompleteMergeGroup(mergeGroup)
+ .assertIsCompleteMergeGroup(otherMergeGroup))
.assertNoOtherClassesMerged();
}
}
@@ -244,7 +258,7 @@
}
}
assertEquals(
- kotlinParameters.getLambdaGeneration().isInvokeDynamic() ? 0 : 2, lambdasInOutput.size());
+ kotlinParameters.getLambdaGeneration().isInvokeDynamic() ? 0 : 1, lambdasInOutput.size());
}
private String getExpectedOutput() {
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialJavaStyleTest.java b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialJavaStyleTest.java
index e60c8b6..3665e88 100644
--- a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialJavaStyleTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialJavaStyleTest.java
@@ -152,20 +152,17 @@
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 0),
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 1))
.assertIsCompleteMergeGroup(
+ SyntheticItemsTestUtils.syntheticLambdaClass(innerClassReference, 0),
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 2),
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 3))
.assertIsCompleteMergeGroup(
SyntheticItemsTestUtils.syntheticLambdaClass(innerClassReference, 1),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 6),
- SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 7))
- .assertIsCompleteMergeGroup(
- SyntheticItemsTestUtils.syntheticLambdaClass(innerClassReference, 0),
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 4),
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, 5))
.assertClassReferencesNotMerged(
SyntheticItemsTestUtils.syntheticLambdaClass(innerClassReference, 2),
SyntheticItemsTestUtils.syntheticLambdaClass(innerClassReference, 3));
- for (int id = 8; id < 30; id++) {
+ for (int id = 6; id < 30; id++) {
inspector.assertClassReferencesNotMerged(
SyntheticItemsTestUtils.syntheticLambdaClass(mainClassReference, id));
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialKotlinStyleTest.java b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialKotlinStyleTest.java
index 2b9fc2d..059bec4 100644
--- a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialKotlinStyleTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTrivialKotlinStyleTest.java
@@ -9,7 +9,6 @@
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
@@ -107,22 +106,27 @@
inspector.applyIf(
kotlinParameters.getLambdaGeneration().isClass(),
i -> {
- List<ClassReference> group = new ArrayList<>();
- group.add(
+ i.assertIsCompleteMergeGroup(
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testStateless$11"));
- group.add(
+ getTestName(), "MainKt$testStateless$3"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$4"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$5"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$6"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$7"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$8"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$9"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$10"),
+ lambdasInInput.getKStyleLambdaReferenceFromTypeName(
+ getTestName(), "MainKt$testStateless$11"),
lambdasInInput.getKStyleLambdaReferenceFromTypeName(
getTestName(), "MainKt$testStateless$12"));
- if (kotlinParameters
- .getCompilerVersion()
- .isBetweenBothIncluded(
- KotlinCompilerVersion.KOTLINC_1_5_0, KotlinCompilerVersion.KOTLINC_1_6_0)) {
- group.add(
- lambdasInInput.getKStyleLambdaReferenceFromTypeName(
- getTestName(), "MainKt$testStateless$6"));
- }
- i.assertIsCompleteMergeGroup(group);
},
i ->
i.assertIsCompleteMergeGroup(
@@ -140,7 +144,10 @@
}
}
assertEquals(
- kotlinParameters.getLambdaGeneration().isInvokeDynamic() ? 0 : 1, lambdasInOutput.size());
+ kotlinParameters.getLambdaGeneration().isInvokeDynamic()
+ ? 0
+ : allowAccessModification && parameters.isCfRuntime() ? 1 : 2,
+ lambdasInOutput.size());
}
private String getExpectedOutput() {
diff --git a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
index 8c3f9dc..9abbb74 100644
--- a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
+++ b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
@@ -102,6 +102,8 @@
"}",
"-neverclassinline class *",
"-neverinline @adaptresourcefilenames.NoInliningOfDefaultInitializer class * { <init>(); }",
+ "-nohorizontalclassmerging class adaptresourcefilenames.B",
+ "-nohorizontalclassmerging class adaptresourcefilenames.B$Inner",
"-nohorizontalclassmerging class adaptresourcefilenames.pkg.C",
"-nohorizontalclassmerging class adaptresourcefilenames.pkg.innerpkg.D");
}
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
index e7ef37a..5bc8990 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
@@ -3,9 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming.applymapping.sourcelibrary;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -147,7 +147,7 @@
ClassSubject sub = inspector.clazz(ConcreteChecker.class);
assertThat(sub, isPresent());
FieldSubject q = sub.field("java.lang.String", "tag");
- assertThat(q, isAbsent());
+ assertThat(q, isPresentIf(parameters.canInitNewInstanceUsingSuperclassConstructor()));
MethodSubject y = sub.method("void", "check", ImmutableList.of());
assertThat(y, isPresentAndRenamed());
assertEquals("y", y.getFinalName());
diff --git a/src/test/java/com/android/tools/r8/naming/b123068484/runner/Runner.java b/src/test/java/com/android/tools/r8/naming/b123068484/runner/Runner.java
index 84062c9..be7d821 100644
--- a/src/test/java/com/android/tools/r8/naming/b123068484/runner/Runner.java
+++ b/src/test/java/com/android/tools/r8/naming/b123068484/runner/Runner.java
@@ -3,9 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming.b123068484.runner;
-import com.android.tools.r8.naming.b123068484.data.PublicAbs;
import com.android.tools.r8.naming.b123068484.data.Concrete1;
import com.android.tools.r8.naming.b123068484.data.Concrete2;
+import com.android.tools.r8.naming.b123068484.data.PublicAbs;
public class Runner {
private static int counter = 0;
@@ -18,7 +18,7 @@
}
public static void main(String[] args) {
- PublicAbs instance = create("Runner");
+ PublicAbs instance = create(System.currentTimeMillis() > 0 ? "Runner" : null);
if (instance instanceof Concrete1) {
System.out.println(((Concrete1) instance).strField);
} else {
diff --git a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterMaybeNullTest.java b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterMaybeNullTest.java
index 0d4e8d2..7917f8a 100644
--- a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterMaybeNullTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterMaybeNullTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
@@ -58,8 +58,7 @@
MethodSubject testMethodSubject =
mainClassSubject.uniqueMethodWithOriginalName("test");
assertThat(testMethodSubject, isPresent());
- // TODO(b/296030319): Should be equals.
- assertNotEquals(bClassSubject.asTypeSubject(), testMethodSubject.getParameter(0));
+ assertEquals(bClassSubject.asTypeSubject(), testMethodSubject.getParameter(0));
})
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("B");
diff --git a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterTest.java b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterTest.java
index 0298201..54b5560 100644
--- a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/FieldWithUnknownDynamicTypeIntoParameterTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
@@ -54,8 +54,7 @@
MethodSubject testMethodSubject =
mainClassSubject.uniqueMethodWithOriginalName("test");
assertThat(testMethodSubject, isPresent());
- // TODO(b/296030319): Should be equals.
- assertNotEquals(bClassSubject.asTypeSubject(), testMethodSubject.getParameter(0));
+ assertEquals(bClassSubject.asTypeSubject(), testMethodSubject.getParameter(0));
})
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("B");
diff --git a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/UpwardsInterfacePropagationToLibraryOrClasspathMethodTest.java b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/UpwardsInterfacePropagationToLibraryOrClasspathMethodTest.java
index 52b3beb..e1b8630 100644
--- a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/UpwardsInterfacePropagationToLibraryOrClasspathMethodTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/UpwardsInterfacePropagationToLibraryOrClasspathMethodTest.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.optimize.argumentpropagation;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -101,9 +101,7 @@
.run(parameters.getRuntime(), TestClass.class)
.inspect(
inspector -> {
- assertThat(
- inspector.clazz(Delegate.class).method("void", "libraryMethod", "boolean"),
- isPresent());
+ assertThat(inspector.clazz(Delegate.class), isAbsent());
// Check that boolean argument to libraryMethod was removed for AnotherProgramClass.
inspector
.clazz(AnotherProgramClass.class)
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
index d79c473..56e7b82 100644
--- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
@@ -161,7 +161,8 @@
public static class KeptClass<T> {
private T keptField;
- private T notKeptField;
+
+ @NoFieldTypeStrengthening private T notKeptField;
@SuppressWarnings("unchecked")
public <R> R keptMethod(T t) {