Always print a (unknown) reason for not inlining
Bug: 142108662
Change-Id: Ib0fee5b77e01b51242114a03fd50dc5d7497e2f2
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 9944273..56bfebb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -51,6 +51,7 @@
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MutableCallSiteOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.UpdatableMethodOptimizationInfo;
+import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
import com.android.tools.r8.ir.synthetic.EmulateInterfaceSyntheticCfCodeProvider;
import com.android.tools.r8.ir.synthetic.FieldAccessorSourceCode;
@@ -347,41 +348,77 @@
}
public boolean isInliningCandidate(
- DexEncodedMethod container, Reason inliningReason, AppInfoWithSubtyping appInfo) {
+ DexEncodedMethod container,
+ Reason inliningReason,
+ AppInfoWithSubtyping appInfo,
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
checkIfObsolete();
- return isInliningCandidate(container.method.holder, inliningReason, appInfo);
+ return isInliningCandidate(
+ container.method.holder, inliningReason, appInfo, whyAreYouNotInliningReporter);
}
public boolean isInliningCandidate(
- DexType containerType, Reason inliningReason, AppInfoWithSubtyping appInfo) {
+ DexType containerType,
+ Reason inliningReason,
+ AppInfoWithSubtyping appInfo,
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
checkIfObsolete();
if (isClassInitializer()) {
// This will probably never happen but never inline a class initializer.
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
+
if (inliningReason == Reason.FORCE) {
// Make sure we would be able to inline this normally.
- if (!isInliningCandidate(containerType, Reason.SIMPLE, appInfo)) {
+ if (!isInliningCandidate(
+ containerType, Reason.SIMPLE, appInfo, whyAreYouNotInliningReporter)) {
// If not, raise a flag, because some optimizations that depend on force inlining would
// silently produce an invalid code, which is worse than an internal error.
throw new InternalCompilerError("FORCE inlining on non-inlinable: " + toSourceString());
}
return true;
}
+
// TODO(b/128967328): inlining candidate should satisfy all states if multiple states are there.
switch (compilationState) {
case PROCESSED_INLINING_CANDIDATE_ANY:
return true;
+
case PROCESSED_INLINING_CANDIDATE_SUBCLASS:
- return appInfo.isSubtype(containerType, method.holder);
- case PROCESSED_INLINING_CANDIDATE_SAME_PACKAGE:
- return containerType.isSamePackage(method.holder);
- case PROCESSED_INLINING_CANDIDATE_SAME_NEST:
- return NestUtils.sameNest(containerType, method.holder, appInfo);
- case PROCESSED_INLINING_CANDIDATE_SAME_CLASS:
- return containerType == method.holder;
- default:
+ if (appInfo.isSubtype(containerType, method.holder)) {
+ return true;
+ }
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
+
+ case PROCESSED_INLINING_CANDIDATE_SAME_PACKAGE:
+ if (containerType.isSamePackage(method.holder)) {
+ return true;
+ }
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return false;
+
+ case PROCESSED_INLINING_CANDIDATE_SAME_NEST:
+ if (NestUtils.sameNest(containerType, method.holder, appInfo)) {
+ return true;
+ }
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return false;
+
+ case PROCESSED_INLINING_CANDIDATE_SAME_CLASS:
+ if (containerType == method.holder) {
+ return true;
+ }
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return false;
+
+ case PROCESSED_NOT_INLINING_CANDIDATE:
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return false;
+
+ default:
+ throw new Unreachable();
}
}
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 b408240..d8c4ea7 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
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexClass;
@@ -30,6 +31,7 @@
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.MainDexDirectReferenceTracer;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IteratorUtils;
import com.google.common.collect.Sets;
@@ -74,32 +76,53 @@
}
@Override
+ public boolean isForcedInliningOracle() {
+ return false;
+ }
+
+ @Override
public void finish() {
if (Log.ENABLED && info != null) {
Log.debug(getClass(), info.toString());
}
}
- private DexEncodedMethod validateCandidate(InvokeMethod invoke, DexMethod invocationContext) {
- DexEncodedMethod candidate = invoke.lookupSingleTarget(appView, invocationContext.holder);
- if ((candidate == null)
- || (candidate.getCode() == null)
- || appView.definitionFor(candidate.method.holder).isNotProgramClass()) {
+ private boolean isSingleTargetInvalid(
+ InvokeMethod invoke,
+ DexEncodedMethod singleTarget,
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
+ if (singleTarget == null) {
+ throw new Unreachable();
+ }
+
+ if (!singleTarget.hasCode()) {
if (info != null) {
info.exclude(invoke, "No inlinee");
}
- return null;
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
}
+
+ if (appView.definitionFor(singleTarget.method.holder).isNotProgramClass()) {
+ if (info != null) {
+ info.exclude(invoke, "No inlinee");
+ }
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
+ }
+
// Ignore the implicit receiver argument.
int numberOfArguments =
- invoke.arguments().size() - (invoke.isInvokeMethodWithReceiver() ? 1 : 0);
- if (numberOfArguments != candidate.method.getArity()) {
+ invoke.arguments().size() - BooleanUtils.intValue(invoke.isInvokeMethodWithReceiver());
+ if (numberOfArguments != singleTarget.method.getArity()) {
if (info != null) {
info.exclude(invoke, "Argument number mismatch");
}
- return null;
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
}
- return candidate;
+
+ return false;
}
private Reason computeInliningReason(DexEncodedMethod target) {
@@ -133,7 +156,8 @@
InvokeStatic invoke,
DexEncodedMethod method,
DexEncodedMethod target,
- ClassInitializationAnalysis classInitializationAnalysis) {
+ ClassInitializationAnalysis classInitializationAnalysis,
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
// Only proceed with inlining a static invoke if:
// - the holder for the target is a subtype of the holder for the method,
// - the target method always triggers class initialization of its holder before any other side
@@ -172,7 +196,12 @@
//
// For simplicity, we are conservative and consider all interfaces, not only the ones with
// default methods.
- return !clazz.classInitializationMayHaveSideEffects(appView);
+ if (!clazz.classInitializationMayHaveSideEffects(appView)) {
+ return true;
+ }
+
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return false;
}
private synchronized boolean isDoubleInliningTarget(DexEncodedMethod candidate) {
@@ -181,9 +210,13 @@
&& candidate.getCode().estimatedSizeForInliningAtMost(10);
}
- private boolean passesInliningConstraints(InvokeMethod invoke, DexEncodedMethod candidate,
- Reason reason) {
+ private boolean passesInliningConstraints(
+ InvokeMethod invoke,
+ DexEncodedMethod candidate,
+ Reason reason,
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
if (candidate.getOptimizationInfo().neverInline()) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -192,6 +225,7 @@
if (method.isInstanceInitializer()
&& appView.options().isGeneratingClassFiles()
&& reason != Reason.FORCE) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -202,6 +236,7 @@
if (info != null) {
info.exclude(invoke, "direct recursion");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -214,6 +249,7 @@
if (info != null) {
info.exclude(invoke, "is processed in parallel");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -221,11 +257,13 @@
if (options.featureSplitConfiguration != null
&& !options.featureSplitConfiguration.inSameFeatureOrBase(
candidate.method, method.method)) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
if (options.testing.validInliningReasons != null
&& !options.testing.validInliningReasons.contains(reason)) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -234,6 +272,7 @@
if (info != null) {
info.exclude(invoke, "target does not have right access");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -245,10 +284,12 @@
if (info != null) {
info.exclude(invoke, "Do not inline target if method holder is an interface class");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
if (holder.isNotProgramClass()) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -257,6 +298,7 @@
if (info != null) {
info.exclude(invoke, "target is synchronized");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -272,11 +314,13 @@
if (info != null) {
info.exclude(invoke, "target is not ready for double inlining");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
}
} else if (reason == Reason.SIMPLE
&& !satisfiesRequirementsForSimpleInlining(invoke, candidate)) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
@@ -289,6 +333,7 @@
if (info != null) {
info.exclude(invoke, "target has references beyond main dex");
}
+ whyAreYouNotInliningReporter.reportUnknownReason();
return false;
}
// Allow inlining into the classes in the main dex dependent set without restrictions.
@@ -348,13 +393,17 @@
DexEncodedMethod singleTarget,
DexMethod invocationContext,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
- DexEncodedMethod candidate = validateCandidate(invoke, invocationContext);
- if (candidate == null || inliner.isBlackListed(candidate)) {
+ if (isSingleTargetInvalid(invoke, singleTarget, whyAreYouNotInliningReporter)) {
return null;
}
- Reason reason = computeInliningReason(candidate);
- if (!candidate.isInliningCandidate(method, reason, appView.appInfo())) {
+ if (inliner.isBlackListed(singleTarget, whyAreYouNotInliningReporter)) {
+ return null;
+ }
+
+ Reason reason = computeInliningReason(singleTarget);
+ if (!singleTarget.isInliningCandidate(
+ method, reason, appView.appInfo(), whyAreYouNotInliningReporter)) {
// Abort inlining attempt if the single target is not an inlining candidate.
if (info != null) {
info.exclude(invoke, "target is not identified for inlining");
@@ -362,35 +411,38 @@
return null;
}
- if (!passesInliningConstraints(invoke, candidate, reason)) {
+ if (!passesInliningConstraints(invoke, singleTarget, reason, whyAreYouNotInliningReporter)) {
return null;
}
if (info != null) {
- info.include(invoke.getType(), candidate);
+ info.include(invoke.getType(), singleTarget);
}
Value receiver = invoke.getReceiver();
if (receiver.getTypeLattice().isDefinitelyNull()) {
// A definitely null receiver will throw an error on call site.
+ whyAreYouNotInliningReporter.reportUnknownReason();
return null;
}
- InlineAction action = new InlineAction(candidate, invoke, reason);
+ InlineAction action = new InlineAction(singleTarget, invoke, reason);
if (receiver.getTypeLattice().isNullable()) {
assert !receiver.getTypeLattice().isDefinitelyNull();
// When inlining an instance method call, we need to preserve the null check for the
// receiver. Therefore, if the receiver may be null and the candidate inlinee does not
// throw if the receiver is null before any other side effect, then we must synthesize a
// null check.
- if (!candidate.getOptimizationInfo().checksNullReceiverBeforeAnySideEffect()) {
+ if (!singleTarget.getOptimizationInfo().checksNullReceiverBeforeAnySideEffect()) {
InternalOptions options = appView.options();
if (!options.enableInliningOfInvokesWithNullableReceivers) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return null;
}
if (!options.nullableReceiverInliningFilter.isEmpty()
&& !options.nullableReceiverInliningFilter.contains(
invoke.getInvokedMethod().toSourceString())) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
return null;
}
if (Log.ENABLED && Log.isLoggingEnabledFor(Inliner.class)) {
@@ -403,7 +455,6 @@
action.setShouldSynthesizeNullCheckForReceiver();
}
}
-
return action;
}
@@ -414,14 +465,18 @@
DexMethod invocationContext,
ClassInitializationAnalysis classInitializationAnalysis,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
- DexEncodedMethod candidate = validateCandidate(invoke, invocationContext);
- if (candidate == null || inliner.isBlackListed(candidate)) {
+ if (isSingleTargetInvalid(invoke, singleTarget, whyAreYouNotInliningReporter)) {
return null;
}
- Reason reason = computeInliningReason(candidate);
+ if (inliner.isBlackListed(singleTarget, whyAreYouNotInliningReporter)) {
+ return null;
+ }
+
+ Reason reason = computeInliningReason(singleTarget);
// Determine if this should be inlined no matter how big it is.
- if (!candidate.isInliningCandidate(method, reason, appView.appInfo())) {
+ if (!singleTarget.isInliningCandidate(
+ method, reason, appView.appInfo(), whyAreYouNotInliningReporter)) {
// Abort inlining attempt if the single target is not an inlining candidate.
if (info != null) {
info.exclude(invoke, "target is not identified for inlining");
@@ -430,21 +485,22 @@
}
// Abort inlining attempt if we can not guarantee class for static target has been initialized.
- if (!canInlineStaticInvoke(invoke, method, candidate, classInitializationAnalysis)) {
+ if (!canInlineStaticInvoke(
+ invoke, method, singleTarget, classInitializationAnalysis, whyAreYouNotInliningReporter)) {
if (info != null) {
info.exclude(invoke, "target is static but we cannot guarantee class has been initialized");
}
return null;
}
- if (!passesInliningConstraints(invoke, candidate, reason)) {
+ if (!passesInliningConstraints(invoke, singleTarget, reason, whyAreYouNotInliningReporter)) {
return null;
}
if (info != null) {
- info.include(invoke.getType(), candidate);
+ info.include(invoke.getType(), singleTarget);
}
- return new InlineAction(candidate, invoke, reason);
+ return new InlineAction(singleTarget, invoke, reason);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java
index b44e32c..6c93489 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java
@@ -39,6 +39,11 @@
}
@Override
+ public boolean isForcedInliningOracle() {
+ return true;
+ }
+
+ @Override
public void finish() {}
@Override
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 9b8d8a8..074c6cd 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
@@ -34,12 +34,15 @@
import com.android.tools.r8.ir.desugar.TwrCloseResourceRewriter;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
+import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
+import com.android.tools.r8.kotlin.Kotlin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.MainDexClasses;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.HashMap;
@@ -55,6 +58,8 @@
public class Inliner {
protected final AppView<AppInfoWithLiveness> appView;
+ private final Set<DexMethod> blackList;
+ private final LensCodeRewriter lensCodeRewriter;
final MainDexClasses mainDexClasses;
// State for inlining methods which are known to be called twice.
@@ -63,34 +68,46 @@
private final Set<DexEncodedMethod> doubleInlineSelectedTargets = Sets.newIdentityHashSet();
private final Map<DexEncodedMethod, DexEncodedMethod> doubleInlineeCandidates = new HashMap<>();
- private final Set<DexMethod> blackList = Sets.newIdentityHashSet();
- private final LensCodeRewriter lensCodeRewriter;
-
public Inliner(
AppView<AppInfoWithLiveness> appView,
MainDexClasses mainDexClasses,
LensCodeRewriter lensCodeRewriter) {
+ Kotlin.Intrinsics intrinsics = appView.dexItemFactory().kotlin.intrinsics;
this.appView = appView;
- this.mainDexClasses = mainDexClasses;
+ this.blackList = ImmutableSet.of(intrinsics.throwNpe, intrinsics.throwParameterIsNullException);
this.lensCodeRewriter = lensCodeRewriter;
- fillInBlackList();
+ this.mainDexClasses = mainDexClasses;
}
- private void fillInBlackList() {
- blackList.add(appView.dexItemFactory().kotlin.intrinsics.throwParameterIsNullException);
- blackList.add(appView.dexItemFactory().kotlin.intrinsics.throwNpe);
- }
-
- public boolean isBlackListed(DexEncodedMethod encodedMethod) {
+ boolean isBlackListed(
+ DexEncodedMethod encodedMethod, WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
DexMethod method = encodedMethod.method;
if (encodedMethod.getOptimizationInfo().forceInline()
&& appView.appInfo().neverInline.contains(method)) {
throw new Unreachable();
}
- return blackList.contains(appView.graphLense().getOriginalMethodSignature(method))
- || appView.appInfo().isPinned(method)
- || appView.appInfo().neverInline.contains(method)
- || TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(method, appView);
+
+ if (appView.appInfo().isPinned(method)) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
+ }
+
+ if (blackList.contains(appView.graphLense().getOriginalMethodSignature(method))) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
+ }
+
+ if (appView.appInfo().neverInline.contains(method)) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
+ }
+
+ if (TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(method, appView)) {
+ whyAreYouNotInliningReporter.reportUnknownReason();
+ return true;
+ }
+
+ return false;
}
private ConstraintWithTarget instructionAllowedForInlining(
@@ -738,7 +755,9 @@
}
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter =
- WhyAreYouNotInliningReporter.createFor(singleTarget, appView, context);
+ oracle.isForcedInliningOracle()
+ ? NopWhyAreYouNotInliningReporter.getInstance()
+ : WhyAreYouNotInliningReporter.createFor(singleTarget, appView, context);
InlineAction action =
invoke.computeInlining(
singleTarget,
@@ -747,10 +766,10 @@
classInitializationAnalysis,
whyAreYouNotInliningReporter);
if (action == null) {
- // TODO(b/142108662): Enable assertion once reporting is complete.
- // assert whyAreYouNotInliningReporter.verifyReasonHasBeenReported();
+ assert whyAreYouNotInliningReporter.verifyReasonHasBeenReported();
continue;
}
+
if (!strategy.stillHasBudget(action, whyAreYouNotInliningReporter)) {
assert whyAreYouNotInliningReporter.verifyReasonHasBeenReported();
continue;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
index f289b24..2cbc5a0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
@@ -19,6 +19,8 @@
*/
public interface InliningOracle {
+ boolean isForcedInliningOracle();
+
void finish();
// TODO(b/142116551): This should be equivalent to invoke.lookupSingleTarget(appView, context)!
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 bda91af..8930a2a 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
@@ -39,7 +39,7 @@
import com.android.tools.r8.ir.optimize.classinliner.ClassInliner.EligibilityStatus;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
-import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotKeepingReporter;
+import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotInliningReporter;
import com.android.tools.r8.kotlin.KotlinInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ListUtils;
@@ -911,7 +911,7 @@
defaultOracle.get(),
method.method,
ClassInitializationAnalysis.trivial(),
- NopWhyAreYouNotKeepingReporter.getInstance());
+ NopWhyAreYouNotInliningReporter.getInstance());
if (inlineAction == null) {
return false;
}
@@ -983,7 +983,8 @@
// return false.
return true;
}
- if (!singleTarget.isInliningCandidate(method, Reason.SIMPLE, appView.appInfo())) {
+ if (!singleTarget.isInliningCandidate(
+ method, Reason.SIMPLE, appView.appInfo(), NopWhyAreYouNotInliningReporter.getInstance())) {
// If `singleTarget` is not an inlining candidate, we won't be able to inline it here.
//
// Note that there may be some false negatives here since the method may
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/NopWhyAreYouNotInliningReporter.java
similarity index 77%
rename from src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotKeepingReporter.java
rename to src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotInliningReporter.java
index 1fac475..0858b45 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/NopWhyAreYouNotInliningReporter.java
@@ -8,14 +8,14 @@
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
-public class NopWhyAreYouNotKeepingReporter extends WhyAreYouNotInliningReporter {
+public class NopWhyAreYouNotInliningReporter extends WhyAreYouNotInliningReporter {
- private static final NopWhyAreYouNotKeepingReporter INSTANCE =
- new NopWhyAreYouNotKeepingReporter();
+ private static final NopWhyAreYouNotInliningReporter INSTANCE =
+ new NopWhyAreYouNotInliningReporter();
- private NopWhyAreYouNotKeepingReporter() {}
+ private NopWhyAreYouNotInliningReporter() {}
- public static NopWhyAreYouNotKeepingReporter getInstance() {
+ public static NopWhyAreYouNotInliningReporter getInstance() {
return INSTANCE;
}
@@ -27,6 +27,9 @@
int estimatedNumberOfControlFlowResolutionBlocks, int threshold) {}
@Override
+ public void reportUnknownReason() {}
+
+ @Override
public void reportUnknownTarget() {}
@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 039956c..8834ddf 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
@@ -21,7 +21,7 @@
return new WhyAreYouNotInliningReporterImpl(
callee, context, appView.options().testing.whyAreYouNotInliningConsumer);
}
- return NopWhyAreYouNotKeepingReporter.getInstance();
+ return NopWhyAreYouNotInliningReporter.getInstance();
}
public static void handleInvokeWithUnknownTarget(
@@ -49,6 +49,8 @@
public abstract void reportPotentialExplosionInExceptionalControlFlowResolutionBlocks(
int estimatedNumberOfControlFlowResolutionBlocks, int threshold);
+ public abstract void reportUnknownReason();
+
abstract void reportUnknownTarget();
public abstract void reportUnsafeConstructorInliningDueToFinalFieldAssignment(
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 6fc1f50..6340db4 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
@@ -30,8 +30,12 @@
output.print(callee.method.toSourceString());
output.print("` was not inlined into `");
output.print(context.method.toSourceString());
- output.print("`: ");
- output.println(reason);
+ if (reason != null) {
+ output.print("`: ");
+ output.println(reason);
+ } else {
+ output.println("`.");
+ }
reasonHasBeenReported = true;
}
@@ -55,6 +59,12 @@
threshold);
}
+ // TODO(b/142108662): Always report a meaningful reason.
+ @Override
+ public void reportUnknownReason() {
+ print(null);
+ }
+
@Override
public void reportUnknownTarget() {
print("could not find a single target.");
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java
index 16430eb..f500c06 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaClassValidator.java
@@ -25,6 +25,8 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.optimize.Inliner.Reason;
+import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotInliningReporter;
+import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.optimize.lambda.CaptureSignature;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroup.LambdaStructureError;
import com.android.tools.r8.kotlin.Kotlin;
@@ -111,8 +113,11 @@
// can safely use a fake one here.
DexType fakeLambdaGroupType = kotlin.factory.createType(
"L" + group.getTypePackage() + "-$$LambdaGroup$XXXX;");
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter =
+ NopWhyAreYouNotInliningReporter.getInstance();
for (DexEncodedMethod method : lambda.virtualMethods()) {
- if (!method.isInliningCandidate(fakeLambdaGroupType, Reason.SIMPLE, appInfo)) {
+ if (!method.isInliningCandidate(
+ fakeLambdaGroupType, Reason.SIMPLE, appInfo, whyAreYouNotInliningReporter)) {
throw structureError("method " + method.method.toSourceString() +
" is not inline-able into lambda group class");
}