Support for -whyareyounotinlining in Inliner.canInlineInstanceInitializer()
Bug: 142108662
Change-Id: Ic22afe064cf722b93fe81ed73a3b72d213c35640
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index d23805d..b408240 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
@@ -506,6 +507,8 @@
if (receiver == thisValue) {
// The <init>() call of the constructor must be on the same class.
if (calleeMethodHolder != invokedMethod.holder) {
+ whyAreYouNotInliningReporter
+ .reportUnsafeConstructorInliningDueToIndirectConstructorCall(initCall);
return false;
}
initCallsOnThis.add(initCall);
@@ -513,9 +516,12 @@
}
} else if (instruction.isInstancePut()) {
// Final fields may not be initialized outside of a constructor in the enclosing class.
- DexField field = instruction.asInstancePut().getField();
+ InstancePut instancePut = instruction.asInstancePut();
+ DexField field = instancePut.getField();
DexEncodedField target = appView.appInfo().lookupInstanceTarget(field.holder, field);
if (target == null || target.accessFlags.isFinal()) {
+ whyAreYouNotInliningReporter.reportUnsafeConstructorInliningDueToFinalFieldAssignment(
+ instancePut);
return false;
}
}
@@ -530,6 +536,8 @@
Value root = inValue.getAliasedValue();
if (root == thisValue) {
inlinee.returnMarkingColor(markingColor);
+ whyAreYouNotInliningReporter.reportUnsafeConstructorInliningDueToUninitializedObjectUse(
+ instruction);
return false;
}
}
@@ -546,6 +554,8 @@
Value root = inValue.getAliasedValue();
if (root == thisValue) {
inlinee.returnMarkingColor(markingColor);
+ whyAreYouNotInliningReporter
+ .reportUnsafeConstructorInliningDueToUninitializedObjectUse(instruction);
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index b6ae500..9b8d8a8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -777,8 +777,7 @@
if (singleTarget.isInstanceInitializer()
&& !strategy.canInlineInstanceInitializer(
inlinee.code, whyAreYouNotInliningReporter)) {
- // TODO(b/142108662): Enable assertion once reporting is complete.
- // assert whyAreYouNotInliningReporter.verifyReasonHasBeenReported();
+ assert whyAreYouNotInliningReporter.verifyReasonHasBeenReported();
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotKeepingReporter.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotKeepingReporter.java
index dce73a6..1fac475 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotKeepingReporter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotKeepingReporter.java
@@ -4,6 +4,10 @@
package com.android.tools.r8.ir.optimize.inliner;
+import com.android.tools.r8.ir.code.InstancePut;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InvokeDirect;
+
public class NopWhyAreYouNotKeepingReporter extends WhyAreYouNotInliningReporter {
private static final NopWhyAreYouNotKeepingReporter INSTANCE =
@@ -26,6 +30,15 @@
public void reportUnknownTarget() {}
@Override
+ public void reportUnsafeConstructorInliningDueToFinalFieldAssignment(InstancePut instancePut) {}
+
+ @Override
+ public void reportUnsafeConstructorInliningDueToIndirectConstructorCall(InvokeDirect invoke) {}
+
+ @Override
+ public void reportUnsafeConstructorInliningDueToUninitializedObjectUse(Instruction user) {}
+
+ @Override
public void reportWillExceedInstructionBudget(int numberOfInstructions, int threshold) {}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
index 6b5d786..039956c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
@@ -6,6 +6,9 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.ir.code.InstancePut;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.Collection;
@@ -48,6 +51,14 @@
abstract void reportUnknownTarget();
+ public abstract void reportUnsafeConstructorInliningDueToFinalFieldAssignment(
+ InstancePut instancePut);
+
+ public abstract void reportUnsafeConstructorInliningDueToIndirectConstructorCall(
+ InvokeDirect invoke);
+
+ public abstract void reportUnsafeConstructorInliningDueToUninitializedObjectUse(Instruction user);
+
public abstract void reportWillExceedInstructionBudget(int numberOfInstructions, int threshold);
public abstract boolean verifyReasonHasBeenReported();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
index c59ddba..6fc1f50 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
@@ -5,6 +5,9 @@
package com.android.tools.r8.ir.optimize.inliner;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.ir.code.InstancePut;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InvokeDirect;
import java.io.PrintStream;
class WhyAreYouNotInliningReporterImpl extends WhyAreYouNotInliningReporter {
@@ -58,6 +61,29 @@
}
@Override
+ public void reportUnsafeConstructorInliningDueToFinalFieldAssignment(InstancePut instancePut) {
+ print(
+ "final field `"
+ + instancePut.getField()
+ + "` must be initialized in a constructor of `"
+ + callee.method.holder.toSourceString()
+ + "`.");
+ }
+
+ @Override
+ public void reportUnsafeConstructorInliningDueToIndirectConstructorCall(InvokeDirect invoke) {
+ print(
+ "must invoke a constructor from the class being instantiated (would invoke `"
+ + invoke.getInvokedMethod().toSourceString()
+ + "`).");
+ }
+
+ @Override
+ public void reportUnsafeConstructorInliningDueToUninitializedObjectUse(Instruction user) {
+ print("would lead to use of uninitialized object (user: `" + user.toString() + "`).");
+ }
+
+ @Override
public void reportWillExceedInstructionBudget(int numberOfInstructions, int threshold) {
printWithExceededThreshold(
"would exceed the caller's instruction budget",