Towards context sensitive instance initializer info
This makes the instance initializer info on MethodOptimizationInfo context sensitive.
Since the computed instance initializer info is currently true in all contexts a special AlwaysTrueInstanceInitializerInfoContext is used.
Follow up work will need to compute different instance initializer info instances that are only true in specific contexts (e.g., when a parameter is guaranteed to have a specific value).
Change-Id: I993eafee4b4599416bd532a5c8fa88c33514accf
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
index 6e46731..2cf0214 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
@@ -21,7 +21,7 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeNewArray;
import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.NewArrayFilledData;
@@ -255,7 +255,7 @@
}
// Find the single constructor invocation.
- InvokeMethod constructorInvoke =
+ InvokeDirect constructorInvoke =
newInstance.getUniqueConstructorInvoke(appView.dexItemFactory());
if (constructorInvoke == null || constructorInvoke.getInvokedMethod().holder != clazz.type) {
// Didn't find a (valid) constructor invocation, give up.
@@ -269,7 +269,7 @@
}
InstanceInitializerInfo initializerInfo =
- constructor.getOptimizationInfo().getInstanceInitializerInfo();
+ constructor.getOptimizationInfo().getInstanceInitializerInfo(constructorInvoke);
List<DexEncodedField> fields = clazz.getDirectAndIndirectInstanceFields(appView);
if (!fields.isEmpty()) {
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 d0fd119..d0a86ef 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
@@ -162,7 +162,7 @@
singleTarget
.getDefinition()
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getInstanceInitializerInfo(invoke)
.fieldInitializationInfos();
// Synchronize on the lattice element (abstractInstanceFieldValuesForClass) in case we process
@@ -232,7 +232,7 @@
InstanceFieldInitializationInfo fieldInitializationInfo =
method
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getContextInsensitiveInstanceInitializerInfo()
.fieldInitializationInfos()
.get(field);
if (fieldInitializationInfo.isSingleValue()) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
index 17ee50a..443ac30 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -147,7 +147,7 @@
singleTarget
.getDefinition()
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getInstanceInitializerInfo(invoke)
.fieldInitializationInfos();
for (DexEncodedField field : singleTarget.getHolder().instanceFields()) {
assert isSubjectToOptimization(field);
@@ -169,7 +169,7 @@
parentConstructor
.getDefinition()
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getInstanceInitializerInfo(parentConstructorCall)
.fieldInitializationInfos();
infos.forEach(
appView,
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index ca922bf..9be6c55 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -348,7 +348,7 @@
singleTarget
.getDefinition()
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getInstanceInitializerInfo(uniqueConstructorInvoke)
.fieldInitializationInfos();
if (initializationInfos.isEmpty()) {
return ObjectState.empty();
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index c61ca0a..b4ff341 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -202,7 +202,7 @@
return singleTarget
.getDefinition()
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getInstanceInitializerInfo(this)
.readSet();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
index 8928a4d..fdaf8f0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
@@ -255,7 +255,9 @@
DexEncodedMethod singleTargetDefinition = singleTarget.getDefinition();
MethodOptimizationInfo optimizationInfo = singleTargetDefinition.getOptimizationInfo();
if (singleTargetDefinition.isInstanceInitializer()) {
- InstanceInitializerInfo initializerInfo = optimizationInfo.getInstanceInitializerInfo();
+ assert isInvokeDirect();
+ InstanceInitializerInfo initializerInfo =
+ optimizationInfo.getInstanceInitializerInfo(asInvokeDirect());
if (!initializerInfo.mayHaveOtherSideEffectsThanInstanceFieldAssignments()) {
return !isInvokeDirect();
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
index 4379da1..44f5990 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
-import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.BitSet;
import java.util.Set;
@@ -60,8 +60,8 @@
void setClassInlinerEligibility(DexEncodedMethod method, ClassInlinerEligibilityInfo eligibility);
- void setInstanceInitializerInfo(
- DexEncodedMethod method, InstanceInitializerInfo instanceInitializerInfo);
+ void setInstanceInitializerInfoCollection(
+ DexEncodedMethod method, InstanceInitializerInfoCollection instanceInitializerInfoCollection);
void setInitializerEnablingJavaVmAssertions(DexEncodedMethod method);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index aea6ae7..3745120 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -366,7 +366,7 @@
}
InstanceInitializerInfo instanceInitializerInfo =
- singleTarget.getDefinition().getOptimizationInfo().getInstanceInitializerInfo();
+ singleTarget.getDefinition().getOptimizationInfo().getInstanceInitializerInfo(invoke);
if (instanceInitializerInfo.mayHaveOtherSideEffectsThanInstanceFieldAssignments()) {
killAllNonFinalActiveFields();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index 550a0e1..e080808 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -826,7 +826,7 @@
// Check that the `eligibleInstance` does not escape via the constructor.
InstanceInitializerInfo instanceInitializerInfo =
- singleTarget.getDefinition().getOptimizationInfo().getInstanceInitializerInfo();
+ singleTarget.getDefinition().getOptimizationInfo().getInstanceInitializerInfo(invoke);
if (instanceInitializerInfo.receiverMayEscapeOutsideConstructorChain()) {
return null;
}
@@ -856,7 +856,11 @@
NopWhyAreYouNotInliningReporter.getInstance())) {
return null;
}
- parent = encodedParentMethod.getOptimizationInfo().getInstanceInitializerInfo().getParent();
+ parent =
+ encodedParentMethod
+ .getOptimizationInfo()
+ .getContextInsensitiveInstanceInitializerInfo()
+ .getParent();
}
return new InliningInfo(singleTarget, eligibleClass.type);
@@ -1317,7 +1321,7 @@
return false;
}
InstanceInitializerInfo initializerInfo =
- definition.getOptimizationInfo().getInstanceInitializerInfo();
+ definition.getOptimizationInfo().getContextInsensitiveInstanceInitializerInfo();
return initializerInfo.receiverNeverEscapesOutsideConstructorChain();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 8268c65..2d46582 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -698,7 +698,7 @@
hasInstanceInitializer = true;
if (directMethod
.getOptimizationInfo()
- .getInstanceInitializerInfo()
+ .getContextInsensitiveInstanceInitializerInfo()
.mayHaveOtherSideEffectsThanInstanceFieldAssignments()) {
markEnumAsUnboxable(Reason.INVALID_INIT, enumClass);
break;
@@ -714,6 +714,7 @@
}
if (enumClass.classInitializationMayHaveSideEffects(appView)) {
+ enumClass.classInitializationMayHaveSideEffects(appView);
markEnumAsUnboxable(Reason.INVALID_CLINIT, enumClass);
}
});
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
index 0e3e339..b2b10ae 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
+import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
@@ -82,7 +83,12 @@
}
@Override
- public InstanceInitializerInfo getInstanceInitializerInfo() {
+ public InstanceInitializerInfo getContextInsensitiveInstanceInitializerInfo() {
+ return DefaultInstanceInitializerInfo.getInstance();
+ }
+
+ @Override
+ public InstanceInitializerInfo getInstanceInitializerInfo(InvokeDirect invoke) {
return DefaultInstanceInitializerInfo.getInstance();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
index f919a1e..cf7c4ee 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
@@ -68,7 +69,9 @@
public abstract Set<DexType> getInitializedClassesOnNormalExit();
- public abstract InstanceInitializerInfo getInstanceInitializerInfo();
+ public abstract InstanceInitializerInfo getContextInsensitiveInstanceInitializerInfo();
+
+ public abstract InstanceInitializerInfo getInstanceInitializerInfo(InvokeDirect invoke);
public abstract boolean isInitializerEnablingJavaVmAssertions();
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 e3ab9af..09c4a5d 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
@@ -93,8 +93,8 @@
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsageBuilder;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeAnalyzer;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
-import com.android.tools.r8.ir.optimize.info.initializer.DefaultInstanceInitializerInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.ir.optimize.info.initializer.NonTrivialInstanceInitializerInfo;
import com.android.tools.r8.ir.optimize.typechecks.CheckCastAndInstanceOfMethodSpecialization;
import com.android.tools.r8.kotlin.Kotlin;
@@ -437,11 +437,8 @@
NonTrivialInstanceInitializerInfo.Builder builder =
NonTrivialInstanceInitializerInfo.builder(instanceFieldInitializationInfos);
InstanceInitializerInfo instanceInitializerInfo = analyzeInstanceInitializer(code, builder);
- feedback.setInstanceInitializerInfo(
- method,
- instanceInitializerInfo != null
- ? instanceInitializerInfo
- : DefaultInstanceInitializerInfo.getInstance());
+ feedback.setInstanceInitializerInfoCollection(
+ method, InstanceInitializerInfoCollection.of(instanceInitializerInfo));
}
// This method defines trivial instance initializer as follows:
@@ -586,7 +583,8 @@
builder.setParent(invokedMethod);
break;
}
- builder.merge(singleTarget.getOptimizationInfo().getInstanceInitializerInfo());
+ builder.merge(
+ singleTarget.getOptimizationInfo().getInstanceInitializerInfo(invoke));
for (int i = 1; i < invoke.arguments().size(); i++) {
Value argument =
invoke.arguments().get(i).getAliasedValue(aliasesThroughAssumeAndCheckCasts);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
index 07b7ce1..50cb793 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
-import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.AppInfoWithLivenessModifier;
import com.android.tools.r8.utils.IteratorUtils;
@@ -254,10 +254,11 @@
}
@Override
- public synchronized void setInstanceInitializerInfo(
- DexEncodedMethod method, InstanceInitializerInfo instanceInitializerInfo) {
+ public synchronized void setInstanceInitializerInfoCollection(
+ DexEncodedMethod method,
+ InstanceInitializerInfoCollection instanceInitializerInfoCollection) {
getMethodOptimizationInfoForUpdating(method)
- .setInstanceInitializerInfo(instanceInitializerInfo);
+ .setInstanceInitializerInfoCollection(instanceInitializerInfoCollection);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
index 6a28331..12fda15 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
-import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.BitSet;
import java.util.Set;
@@ -115,8 +115,9 @@
DexEncodedMethod method, ClassInlinerEligibilityInfo eligibility) {}
@Override
- public void setInstanceInitializerInfo(
- DexEncodedMethod method, InstanceInitializerInfo instanceInitializerInfo) {}
+ public void setInstanceInitializerInfoCollection(
+ DexEncodedMethod method,
+ InstanceInitializerInfoCollection instanceInitializerInfoCollection) {}
@Override
public void setInitializerEnablingJavaVmAssertions(DexEncodedMethod method) {}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
index 9a3bb51..5840ea6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
-import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.BitSet;
import java.util.Set;
@@ -165,9 +165,12 @@
}
@Override
- public void setInstanceInitializerInfo(
- DexEncodedMethod method, InstanceInitializerInfo instanceInitializerInfo) {
- method.getMutableOptimizationInfo().setInstanceInitializerInfo(instanceInitializerInfo);
+ public void setInstanceInitializerInfoCollection(
+ DexEncodedMethod method,
+ InstanceInitializerInfoCollection instanceInitializerInfoCollection) {
+ method
+ .getMutableOptimizationInfo()
+ .setInstanceInitializerInfoCollection(instanceInitializerInfoCollection);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
index 6d9fc9f..877c72d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
@@ -12,11 +12,12 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
+import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
-import com.android.tools.r8.ir.optimize.info.initializer.DefaultInstanceInitializerInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BooleanUtils;
import java.util.BitSet;
@@ -39,8 +40,8 @@
private BridgeInfo bridgeInfo = null;
private ClassInlinerEligibilityInfo classInlinerEligibility =
DefaultMethodOptimizationInfo.UNKNOWN_CLASS_INLINER_ELIGIBILITY;
- private InstanceInitializerInfo instanceInitializerInfo =
- DefaultInstanceInitializerInfo.getInstance();
+ private InstanceInitializerInfoCollection instanceInitializerInfoCollection =
+ InstanceInitializerInfoCollection.empty();
private ParameterUsagesInfo parametersUsages =
DefaultMethodOptimizationInfo.UNKNOWN_PARAMETER_USAGE_INFO;
// Stores information about nullability hint per parameter. If set, that means, the method
@@ -138,7 +139,7 @@
inlining = template.inlining;
bridgeInfo = template.bridgeInfo;
classInlinerEligibility = template.classInlinerEligibility;
- instanceInitializerInfo = template.instanceInitializerInfo;
+ instanceInitializerInfoCollection = template.instanceInitializerInfoCollection;
parametersUsages = template.parametersUsages;
nonNullParamOrThrow = template.nonNullParamOrThrow;
nonNullParamOnNormalExits = template.nonNullParamOnNormalExits;
@@ -172,9 +173,8 @@
public UpdatableMethodOptimizationInfo fixupInstanceInitializerInfo(
AppView<AppInfoWithLiveness> appView, GraphLens lens) {
- if (instanceInitializerInfo != null) {
- instanceInitializerInfo = instanceInitializerInfo.rewrittenWithLens(appView, lens);
- }
+ instanceInitializerInfoCollection =
+ instanceInitializerInfoCollection.rewrittenWithLens(appView, lens);
return this;
}
@@ -248,8 +248,13 @@
}
@Override
- public InstanceInitializerInfo getInstanceInitializerInfo() {
- return instanceInitializerInfo;
+ public InstanceInitializerInfo getContextInsensitiveInstanceInitializerInfo() {
+ return instanceInitializerInfoCollection.getContextInsensitive();
+ }
+
+ @Override
+ public InstanceInitializerInfo getInstanceInitializerInfo(InvokeDirect invoke) {
+ return instanceInitializerInfoCollection.get(invoke);
}
@Override
@@ -371,8 +376,9 @@
this.classInlinerEligibility = eligibility;
}
- void setInstanceInitializerInfo(InstanceInitializerInfo instanceInitializerInfo) {
- this.instanceInitializerInfo = instanceInitializerInfo;
+ void setInstanceInitializerInfoCollection(
+ InstanceInitializerInfoCollection instanceInitializerInfoCollection) {
+ this.instanceInitializerInfoCollection = instanceInitializerInfoCollection;
}
void setInitializerEnablingJavaAssertions() {
@@ -520,7 +526,7 @@
// classInlinerEligibility: chances are the method is not an instance method anymore.
classInlinerEligibility = DefaultMethodOptimizationInfo.UNKNOWN_CLASS_INLINER_ELIGIBILITY;
// initializerInfo: the computed initializer info may become invalid.
- instanceInitializerInfo = null;
+ instanceInitializerInfoCollection = InstanceInitializerInfoCollection.empty();
// initializerEnablingJavaAssertions: `this` could trigger <clinit> of the previous holder.
setFlag(
INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/AlwaysTrueInstanceInitializerInfoContext.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/AlwaysTrueInstanceInitializerInfoContext.java
new file mode 100644
index 0000000..12ef51a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/AlwaysTrueInstanceInitializerInfoContext.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.info.initializer;
+
+import com.android.tools.r8.ir.code.InvokeMethod;
+
+public class AlwaysTrueInstanceInitializerInfoContext extends InstanceInitializerInfoContext {
+
+ private static final AlwaysTrueInstanceInitializerInfoContext INSTANCE =
+ new AlwaysTrueInstanceInitializerInfoContext();
+
+ private AlwaysTrueInstanceInitializerInfoContext() {}
+
+ public static AlwaysTrueInstanceInitializerInfoContext getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isAlwaysTrue() {
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfiedBy(InvokeMethod invoke) {
+ return true;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/ContextInsensitiveInstanceInitializerInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/ContextInsensitiveInstanceInitializerInfoCollection.java
new file mode 100644
index 0000000..6cf070d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/ContextInsensitiveInstanceInitializerInfoCollection.java
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.info.initializer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class ContextInsensitiveInstanceInitializerInfoCollection
+ extends InstanceInitializerInfoCollection {
+
+ private final NonTrivialInstanceInitializerInfo info;
+
+ ContextInsensitiveInstanceInitializerInfoCollection(NonTrivialInstanceInitializerInfo info) {
+ this.info = info;
+ }
+
+ @Override
+ public NonTrivialInstanceInitializerInfo getContextInsensitive() {
+ return info;
+ }
+
+ @Override
+ public NonTrivialInstanceInitializerInfo get(InvokeDirect invoke) {
+ return info;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public ContextInsensitiveInstanceInitializerInfoCollection rewrittenWithLens(
+ AppView<AppInfoWithLiveness> appView, GraphLens lens) {
+ NonTrivialInstanceInitializerInfo rewrittenInfo = info.rewrittenWithLens(appView, lens);
+ if (rewrittenInfo != info) {
+ return new ContextInsensitiveInstanceInitializerInfoCollection(rewrittenInfo);
+ }
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/ContextSensitiveInstanceInitializerInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/ContextSensitiveInstanceInitializerInfoCollection.java
new file mode 100644
index 0000000..3347587
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/ContextSensitiveInstanceInitializerInfoCollection.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.info.initializer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map.Entry;
+
+public class ContextSensitiveInstanceInitializerInfoCollection
+ extends InstanceInitializerInfoCollection {
+
+ private final ImmutableMap<InstanceInitializerInfoContext, NonTrivialInstanceInitializerInfo>
+ infos;
+
+ protected ContextSensitiveInstanceInitializerInfoCollection(
+ ImmutableMap<InstanceInitializerInfoContext, NonTrivialInstanceInitializerInfo> infos) {
+ assert !infos.isEmpty();
+ this.infos = infos;
+ }
+
+ @Override
+ public InstanceInitializerInfo getContextInsensitive() {
+ NonTrivialInstanceInitializerInfo result =
+ infos.get(AlwaysTrueInstanceInitializerInfoContext.getInstance());
+ return result != null ? result : DefaultInstanceInitializerInfo.getInstance();
+ }
+
+ @Override
+ public InstanceInitializerInfo get(InvokeDirect invoke) {
+ assert infos.keySet().stream().filter(context -> context.isSatisfiedBy(invoke)).count() <= 1;
+ for (Entry<InstanceInitializerInfoContext, NonTrivialInstanceInitializerInfo> entry :
+ infos.entrySet()) {
+ if (entry.getKey().isSatisfiedBy(invoke)) {
+ return entry.getValue();
+ }
+ }
+ return DefaultInstanceInitializerInfo.getInstance();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public InstanceInitializerInfoCollection rewrittenWithLens(
+ AppView<AppInfoWithLiveness> appView, GraphLens lens) {
+ Builder builder = builder();
+ infos.forEach((context, info) -> builder.put(context, info.rewrittenWithLens(appView, lens)));
+ return builder.build();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java
index c9a7f32..af59b7c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java
@@ -25,6 +25,11 @@
}
@Override
+ public boolean isDefaultInstanceInitializerInfo() {
+ return true;
+ }
+
+ @Override
public DexMethod getParent() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/EmptyInstanceInitializerInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/EmptyInstanceInitializerInfoCollection.java
new file mode 100644
index 0000000..d7d3560
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/EmptyInstanceInitializerInfoCollection.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.info.initializer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class EmptyInstanceInitializerInfoCollection extends InstanceInitializerInfoCollection {
+
+ private static final EmptyInstanceInitializerInfoCollection EMPTY =
+ new EmptyInstanceInitializerInfoCollection();
+
+ private EmptyInstanceInitializerInfoCollection() {}
+
+ public static EmptyInstanceInitializerInfoCollection getInstance() {
+ return EMPTY;
+ }
+
+ @Override
+ public DefaultInstanceInitializerInfo getContextInsensitive() {
+ return DefaultInstanceInitializerInfo.getInstance();
+ }
+
+ @Override
+ public DefaultInstanceInitializerInfo get(InvokeDirect invoke) {
+ return DefaultInstanceInitializerInfo.getInstance();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+
+ @Override
+ public EmptyInstanceInitializerInfoCollection rewrittenWithLens(
+ AppView<AppInfoWithLiveness> appView, GraphLens lens) {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java
index 1e36f40..3865bc1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java
@@ -13,6 +13,18 @@
public abstract class InstanceInitializerInfo {
+ public boolean isDefaultInstanceInitializerInfo() {
+ return false;
+ }
+
+ public boolean isNonTrivialInstanceInitializerInfo() {
+ return false;
+ }
+
+ public NonTrivialInstanceInitializerInfo asNonTrivialInstanceInitializerInfo() {
+ return null;
+ }
+
public abstract DexMethod getParent();
public abstract InstanceFieldInitializationInfoCollection fieldInitializationInfos();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfoCollection.java
new file mode 100644
index 0000000..ce53a6a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfoCollection.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.info.initializer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.MapUtils;
+import com.google.common.collect.ImmutableMap;
+
+public abstract class InstanceInitializerInfoCollection {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static InstanceInitializerInfoCollection empty() {
+ return EmptyInstanceInitializerInfoCollection.getInstance();
+ }
+
+ public static InstanceInitializerInfoCollection of(InstanceInitializerInfo info) {
+ if (info != null && info.isNonTrivialInstanceInitializerInfo()) {
+ return new ContextInsensitiveInstanceInitializerInfoCollection(
+ info.asNonTrivialInstanceInitializerInfo());
+ }
+ return empty();
+ }
+
+ public abstract InstanceInitializerInfo getContextInsensitive();
+
+ public abstract InstanceInitializerInfo get(InvokeDirect invoke);
+
+ public abstract boolean isEmpty();
+
+ public abstract InstanceInitializerInfoCollection rewrittenWithLens(
+ AppView<AppInfoWithLiveness> appView, GraphLens lens);
+
+ public static class Builder {
+
+ private final ImmutableMap.Builder<
+ InstanceInitializerInfoContext, NonTrivialInstanceInitializerInfo>
+ infosBuilder = ImmutableMap.builder();
+
+ private Builder() {}
+
+ public Builder put(InstanceInitializerInfoContext context, InstanceInitializerInfo info) {
+ if (info.isNonTrivialInstanceInitializerInfo()) {
+ infosBuilder.put(context, info.asNonTrivialInstanceInitializerInfo());
+ }
+ return this;
+ }
+
+ public InstanceInitializerInfoCollection build() {
+ ImmutableMap<InstanceInitializerInfoContext, NonTrivialInstanceInitializerInfo> infos =
+ infosBuilder.build();
+ if (infos.isEmpty()) {
+ return empty();
+ }
+ if (infos.size() == 1 && MapUtils.firstKey(infos).isAlwaysTrue()) {
+ return new ContextInsensitiveInstanceInitializerInfoCollection(MapUtils.firstValue(infos));
+ }
+ return new ContextSensitiveInstanceInitializerInfoCollection(infos);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfoContext.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfoContext.java
new file mode 100644
index 0000000..8c28004
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfoContext.java
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.info.initializer;
+
+import com.android.tools.r8.ir.code.InvokeMethod;
+
+public abstract class InstanceInitializerInfoContext {
+
+ public boolean isAlwaysTrue() {
+ return false;
+ }
+
+ public abstract boolean isSatisfiedBy(InvokeMethod invoke);
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java
index 75c74dd..40b3edc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java
@@ -38,6 +38,16 @@
this.parent = parent;
}
+ @Override
+ public boolean isNonTrivialInstanceInitializerInfo() {
+ return true;
+ }
+
+ @Override
+ public NonTrivialInstanceInitializerInfo asNonTrivialInstanceInitializerInfo() {
+ return this;
+ }
+
private static boolean verifyNoUnknownBits(int data) {
int knownBits =
INSTANCE_FIELD_INITIALIZATION_INDEPENDENT_OF_ENVIRONMENT
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
index d0412b7..9b41f18 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.ir.optimize.info.LibraryOptimizationInfoInitializerFeedback;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoFactory;
+import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfoCollection;
import com.android.tools.r8.ir.optimize.info.initializer.NonTrivialInstanceInitializerInfo;
import com.google.common.collect.Sets;
import java.util.BitSet;
@@ -67,11 +68,12 @@
.recordInitializationInfo(
enumMembers.ordinalField, factory.createArgumentInitializationInfo(2))
.build();
- feedback.setInstanceInitializerInfo(
+ feedback.setInstanceInitializerInfoCollection(
enumConstructor,
- NonTrivialInstanceInitializerInfo.builder(fieldInitializationInfos)
- .setParent(dexItemFactory.objectMembers.constructor)
- .build());
+ InstanceInitializerInfoCollection.of(
+ NonTrivialInstanceInitializerInfo.builder(fieldInitializationInfos)
+ .setParent(dexItemFactory.objectMembers.constructor)
+ .build()));
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java b/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java
index 2de5c70..d63c685 100644
--- a/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java
+++ b/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java
@@ -229,7 +229,7 @@
}
InstanceInitializerInfo initializerInfo =
- singleTarget.getDefinition().getOptimizationInfo().getInstanceInitializerInfo();
+ singleTarget.getDefinition().getOptimizationInfo().getInstanceInitializerInfo(invoke);
return initializerInfo.receiverNeverEscapesOutsideConstructorChain();
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/MapUtils.java b/src/main/java/com/android/tools/r8/utils/MapUtils.java
index c899a75..ac79586 100644
--- a/src/main/java/com/android/tools/r8/utils/MapUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/MapUtils.java
@@ -12,6 +12,14 @@
public class MapUtils {
+ public static <K, V> K firstKey(Map<K, V> map) {
+ return map.keySet().iterator().next();
+ }
+
+ public static <K, V> V firstValue(Map<K, V> map) {
+ return map.values().iterator().next();
+ }
+
public static <K, V> Map<K, V> map(
Map<K, V> map,
IntFunction<Map<K, V>> factory,
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java
index 0f85170..d618b52 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java
@@ -50,7 +50,7 @@
@Override
public V get(Object key) {
- return getRepresentativeValue((K) key);
+ return backing.get(key);
}
@Override